diff --git a/src/vs/base/browser/htmlContentRenderer.ts b/src/vs/base/browser/htmlContentRenderer.ts
index a49e4411274..7087efd5e66 100644
--- a/src/vs/base/browser/htmlContentRenderer.ts
+++ b/src/vs/base/browser/htmlContentRenderer.ts
@@ -47,7 +47,7 @@ export function renderFormattedText(formattedText: string, options: RenderOption
* @param content a html element description
* @param actionCallback a callback function for any action links in the string. Argument is the zero-based index of the clicked action.
*/
-export function renderMarkdown(markdown: IMarkdownString, options: RenderOptions = {}): Node {
+export function renderMarkdown(markdown: IMarkdownString, options: RenderOptions = {}): HTMLElement {
const element = createElement(options);
const { codeBlockRenderer, actionCallback } = options;
diff --git a/src/vs/editor/contrib/hover/browser/hover.ts b/src/vs/editor/contrib/hover/browser/hover.ts
index c895d1c9888..c973826bfa7 100644
--- a/src/vs/editor/contrib/hover/browser/hover.ts
+++ b/src/vs/editor/contrib/hover/browser/hover.ts
@@ -23,6 +23,7 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { editorHoverHighlight, editorHoverBackground, editorHoverBorder, textLinkForeground, textCodeBlockBackground } from 'vs/platform/theme/common/colorRegistry';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
+import { MarkdownRenderer } from 'vs/editor/contrib/markdown/browser/markdownRenderer';
@editorContribution
export class ModesHoverController implements editorCommon.IEditorContribution {
@@ -64,9 +65,9 @@ export class ModesHoverController implements editorCommon.IEditorContribution {
this._hideWidgets();
}
}));
-
- this._contentWidget = new ModesContentHoverWidget(editor, openerService, modeService);
- this._glyphWidget = new ModesGlyphHoverWidget(editor, openerService, modeService);
+ const renderer = new MarkdownRenderer(editor, modeService, openerService);
+ this._contentWidget = new ModesContentHoverWidget(editor, renderer);
+ this._glyphWidget = new ModesGlyphHoverWidget(editor, renderer);
}
}
diff --git a/src/vs/editor/contrib/hover/browser/modesContentHover.ts b/src/vs/editor/contrib/hover/browser/modesContentHover.ts
index d181229ba08..9a790a07550 100644
--- a/src/vs/editor/contrib/hover/browser/modesContentHover.ts
+++ b/src/vs/editor/contrib/hover/browser/modesContentHover.ts
@@ -5,22 +5,17 @@
'use strict';
import * as nls from 'vs/nls';
-import URI from 'vs/base/common/uri';
-import { onUnexpectedError } from 'vs/base/common/errors';
import * as dom from 'vs/base/browser/dom';
import { TPromise } from 'vs/base/common/winjs.base';
-import { renderMarkdown } from 'vs/base/browser/htmlContentRenderer';
-import { IOpenerService, NullOpenerService } from 'vs/platform/opener/common/opener';
-import { IModeService } from 'vs/editor/common/services/modeService';
import { IRange, Range } from 'vs/editor/common/core/range';
import { Position } from 'vs/editor/common/core/position';
import { HoverProviderRegistry, Hover, IColor, IColorFormatter } from 'vs/editor/common/modes';
-import { tokenizeToString } from 'vs/editor/common/modes/textToHtmlTokenizer';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { getHover } from '../common/hover';
import { HoverOperation, IHoverComputer } from './hoverOperation';
import { ContentHoverWidget } from './hoverWidgets';
import { IMarkdownString, MarkdownString, isEmptyMarkdownString } from 'vs/base/common/htmlContent';
+import { MarkdownRenderer } from 'vs/editor/contrib/markdown/browser/markdownRenderer';
import { ModelDecorationOptions } from 'vs/editor/common/model/textModelWithDecorations';
import { ColorPickerModel } from 'vs/editor/contrib/colorPicker/browser/colorPickerModel';
import { ColorPickerWidget } from 'vs/editor/contrib/colorPicker/browser/colorPickerWidget';
@@ -166,22 +161,20 @@ export class ModesContentHoverWidget extends ContentHoverWidget {
private _hoverOperation: HoverOperation;
private _highlightDecorations: string[];
private _isChangingDecorations: boolean;
- private _openerService: IOpenerService;
- private _modeService: IModeService;
+ private _markdownRenderer: MarkdownRenderer;
private _shouldFocus: boolean;
private _colorPicker: ColorPickerWidget;
private renderDisposable: IDisposable = EmptyDisposable;
private toDispose: IDisposable[];
- constructor(editor: ICodeEditor, openerService: IOpenerService, modeService: IModeService) {
+ constructor(editor: ICodeEditor, markdownRenderner: MarkdownRenderer) {
super(ModesContentHoverWidget.ID, editor);
this._computer = new ModesContentComputer(this._editor);
this._highlightDecorations = [];
this._isChangingDecorations = false;
- this._openerService = openerService || NullOpenerService;
- this._modeService = modeService;
+ this._markdownRenderer = markdownRenderner;
this._hoverOperation = new HoverOperation(
this._computer,
@@ -312,24 +305,7 @@ export class ModesContentHoverWidget extends ContentHoverWidget {
msg.contents
.filter(contents => !isEmptyMarkdownString(contents))
.forEach(contents => {
- const renderedContents = renderMarkdown(contents, {
- actionCallback: (content) => {
- this._openerService.open(URI.parse(content)).then(void 0, onUnexpectedError);
- },
- codeBlockRenderer: (languageAlias, value): string | TPromise => {
- // In markdown,
- // it is possible that we stumble upon language aliases (e.g.js instead of javascript)
- // it is possible no alias is given in which case we fall back to the current editor lang
- const modeId = languageAlias
- ? this._modeService.getModeIdForLanguageName(languageAlias)
- : this._editor.getModel().getLanguageIdentifier().language;
-
- return this._modeService.getOrCreateMode(modeId).then(_ => {
- return tokenizeToString(value, modeId);
- });
- }
- });
-
+ const renderedContents = this._markdownRenderer.render(contents);
fragment.appendChild($('div.hover-row', null, renderedContents));
});
} else {
diff --git a/src/vs/editor/contrib/hover/browser/modesGlyphHover.ts b/src/vs/editor/contrib/hover/browser/modesGlyphHover.ts
index 75eeb5c7504..522abe7a08e 100644
--- a/src/vs/editor/contrib/hover/browser/modesGlyphHover.ts
+++ b/src/vs/editor/contrib/hover/browser/modesGlyphHover.ts
@@ -8,13 +8,7 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { HoverOperation, IHoverComputer } from './hoverOperation';
import { GlyphHoverWidget } from './hoverWidgets';
import { $ } from 'vs/base/browser/dom';
-import { renderMarkdown } from 'vs/base/browser/htmlContentRenderer';
-import { IOpenerService, NullOpenerService } from 'vs/platform/opener/common/opener';
-import URI from 'vs/base/common/uri';
-import { onUnexpectedError } from 'vs/base/common/errors';
-import { TPromise } from 'vs/base/common/winjs.base';
-import { IModeService } from 'vs/editor/common/services/modeService';
-import { tokenizeToString } from 'vs/editor/common/modes/textToHtmlTokenizer';
+import { MarkdownRenderer } from 'vs/editor/contrib/markdown/browser/markdownRenderer';
import { IMarkdownString, isEmptyMarkdownString } from 'vs/base/common/htmlContent';
export interface IHoverMessage {
@@ -94,16 +88,16 @@ export class ModesGlyphHoverWidget extends GlyphHoverWidget {
private _messages: IHoverMessage[];
private _lastLineNumber: number;
+ private _markdownRenderer: MarkdownRenderer;
private _computer: MarginComputer;
private _hoverOperation: HoverOperation;
- constructor(editor: ICodeEditor, private openerService: IOpenerService, private modeService: IModeService) {
+ constructor(editor: ICodeEditor, markdownRenderer: MarkdownRenderer) {
super(ModesGlyphHoverWidget.ID, editor);
- this.openerService = openerService || NullOpenerService;
-
this._lastLineNumber = -1;
+ this._markdownRenderer = markdownRenderer;
this._computer = new MarginComputer(this._editor);
this._hoverOperation = new HoverOperation(
@@ -166,17 +160,7 @@ export class ModesGlyphHoverWidget extends GlyphHoverWidget {
const fragment = document.createDocumentFragment();
messages.forEach((msg) => {
- const renderedContents = renderMarkdown(msg.value, {
- actionCallback: content => this.openerService.open(URI.parse(content)).then(undefined, onUnexpectedError),
- codeBlockRenderer: (languageAlias, value): string | TPromise => {
- // In markdown, it is possible that we stumble upon language aliases (e.g. js instead of javascript)
- const modeId = this.modeService.getModeIdForLanguageName(languageAlias);
- return this.modeService.getOrCreateMode(modeId).then(_ => {
- return tokenizeToString(value, modeId);
- });
- }
- });
-
+ const renderedContents = this._markdownRenderer.render(msg.value);
fragment.appendChild($('div.hover-row', null, renderedContents));
});
diff --git a/src/vs/editor/contrib/markdown/browser/markdownRenderer.ts b/src/vs/editor/contrib/markdown/browser/markdownRenderer.ts
new file mode 100644
index 00000000000..fe7f3ad7c2b
--- /dev/null
+++ b/src/vs/editor/contrib/markdown/browser/markdownRenderer.ts
@@ -0,0 +1,54 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+'use strict';
+
+import { TPromise } from 'vs/base/common/winjs.base';
+import { IMarkdownString } from 'vs/base/common/htmlContent';
+import { renderMarkdown, RenderOptions } from 'vs/base/browser/htmlContentRenderer';
+import { IOpenerService, NullOpenerService } from 'vs/platform/opener/common/opener';
+import { IModeService } from 'vs/editor/common/services/modeService';
+import URI from 'vs/base/common/uri';
+import { onUnexpectedError } from 'vs/base/common/errors';
+import { tokenizeToString } from 'vs/editor/common/modes/textToHtmlTokenizer';
+import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
+import { optional } from 'vs/platform/instantiation/common/instantiation';
+
+export class MarkdownRenderer {
+
+ private readonly _options: RenderOptions;
+
+ constructor(
+ editor: ICodeEditor,
+ @IModeService private readonly _modeService: IModeService,
+ @optional(IOpenerService) private readonly _openerService: IOpenerService = NullOpenerService,
+ ) {
+ this._options = {
+ actionCallback: (content) => {
+ this._openerService.open(URI.parse(content)).then(void 0, onUnexpectedError);
+ },
+ codeBlockRenderer: (languageAlias, value): string | TPromise => {
+ // In markdown,
+ // it is possible that we stumble upon language aliases (e.g.js instead of javascript)
+ // it is possible no alias is given in which case we fall back to the current editor lang
+ const modeId = languageAlias
+ ? this._modeService.getModeIdForLanguageName(languageAlias)
+ : editor.getModel().getLanguageIdentifier().language;
+
+ return this._modeService.getOrCreateMode(modeId).then(_ => {
+ return tokenizeToString(value, modeId);
+ });
+ }
+ };
+ }
+
+ render(markdown: IMarkdownString, options?: RenderOptions): HTMLElement {
+ if (options) {
+ return renderMarkdown(markdown, { ...options, ...this._options });
+ } else {
+ return renderMarkdown(markdown, this._options);
+ }
+ }
+}