提交 927f38e5 编写于 作者: J Johannes Rieken

use IModeService to get the correct rendering of markedstring and code blocks, fixes #7405

上级 4b048ee9
......@@ -6,6 +6,8 @@
'use strict';
import DOM = require('vs/base/browser/dom');
import {defaultGenerator} from 'vs/base/common/idGenerator';
import {TPromise} from 'vs/base/common/winjs.base';
import {IHTMLContentElement} from 'vs/base/common/htmlContent';
import {marked} from 'vs/base/common/marked/marked';
import {IMouseEvent} from 'vs/base/browser/mouseEvent';
......@@ -14,7 +16,7 @@ export type RenderableContent = string | IHTMLContentElement | IHTMLContentEleme
export interface RenderOptions {
actionCallback?: (content: string, event?: IMouseEvent) => void;
codeBlockRenderer?: (modeId: string, value: string) => string;
codeBlockRenderer?: (modeId: string, value: string) => string | TPromise<string>;
}
/**
......@@ -58,10 +60,6 @@ function _renderHtml(content: IHTMLContentElement, options: RenderOptions = {}):
element.style[key] = content.customStyle[key];
});
}
if (content.code && codeBlockRenderer) {
let html = codeBlockRenderer(content.code.language, content.code.value);
element.innerHTML = html;
}
if (content.children) {
content.children.forEach((child) => {
element.appendChild(renderHtml(child, options));
......@@ -70,7 +68,21 @@ function _renderHtml(content: IHTMLContentElement, options: RenderOptions = {}):
if (content.formattedText) {
renderFormattedText(element, parseFormattedText(content.formattedText), actionCallback);
}
if (content.code && codeBlockRenderer) {
// this is sort of legacy given that we have full
// support for markdown. Turn this into markdown
// and continue
let {language, value} = content.code;
content.markdown = '```' + language + '\n' + value + '\n```';
}
if (content.markdown) {
// signal to code-block render that the
// element has been created
let signalInnerHTML: Function;
const withInnerHTML = new TPromise(c => signalInnerHTML = c);
const renderer = new marked.Renderer();
renderer.link = (href, title, text): string => {
return `<a href="#" data-href="${href}" title="${title || text}">${text}</a>`;
......@@ -81,7 +93,28 @@ function _renderHtml(content: IHTMLContentElement, options: RenderOptions = {}):
if (options.codeBlockRenderer) {
renderer.code = (code, lang) => {
return options.codeBlockRenderer(lang, code);
let value = options.codeBlockRenderer(lang, code);
if (typeof value === 'string') {
return value;
}
if (TPromise.is(value)) {
// when code-block rendering is async we return sync
// but update the node with the real result later.
const id = defaultGenerator.nextId();
TPromise.join([value, withInnerHTML]).done(values => {
let [value] = values;
let span = element.querySelector(`span[data-code="${id}"]`);
if (span) {
span.innerHTML = value;
}
}, err => {
// ignore
});
return `<span data-code="${id}">${code}</span>`;
}
return code;
};
}
......@@ -100,6 +133,7 @@ function _renderHtml(content: IHTMLContentElement, options: RenderOptions = {}):
sanitize: true,
renderer
});
signalInnerHTML();
}
return element;
......
......@@ -12,6 +12,7 @@ import * as platform from 'vs/base/common/platform';
import {TPromise} from 'vs/base/common/winjs.base';
import {IKeyboardEvent} from 'vs/base/browser/keyboardEvent';
import {IOpenerService} from 'vs/platform/opener/common/opener';
import {IModeService} from 'vs/editor/common/services/modeService';
import {KbExpr} from 'vs/platform/keybinding/common/keybindingService';
import {Range} from 'vs/editor/common/core/range';
import {EditorAction} from 'vs/editor/common/editorAction';
......@@ -39,7 +40,8 @@ class ModesHoverController implements editorCommon.IEditorContribution {
}
constructor(editor: ICodeEditor,
@IOpenerService openerService: IOpenerService
@IOpenerService openerService: IOpenerService,
@IModeService modeService: IModeService
) {
this._editor = editor;
......@@ -58,7 +60,7 @@ class ModesHoverController implements editorCommon.IEditorContribution {
}
}));
this._contentWidget = new ModesContentHoverWidget(editor, openerService);
this._contentWidget = new ModesContentHoverWidget(editor, openerService, modeService);
this._glyphWidget = new ModesGlyphHoverWidget(editor);
}
}
......
......@@ -10,10 +10,11 @@ import URI from 'vs/base/common/uri';
import {TPromise} from 'vs/base/common/winjs.base';
import {renderHtml} from 'vs/base/browser/htmlContentRenderer';
import {IOpenerService, NullOpenerService} from 'vs/platform/opener/common/opener';
import {IModeService} from 'vs/editor/common/services/modeService';
import {Range} from 'vs/editor/common/core/range';
import {Position} from 'vs/editor/common/core/position';
import {IRange} from 'vs/editor/common/editorCommon';
import {HoverProviderRegistry, Hover, IMode} from 'vs/editor/common/modes';
import {HoverProviderRegistry, Hover} 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';
......@@ -126,15 +127,17 @@ export class ModesContentHoverWidget extends ContentHoverWidget {
private _highlightDecorations:string[];
private _isChangingDecorations: boolean;
private _openerService: IOpenerService;
private _modeService: IModeService;
private _shouldFocus: boolean;
constructor(editor: ICodeEditor, openerService: IOpenerService) {
constructor(editor: ICodeEditor, openerService: IOpenerService, modeService: IModeService) {
super(ModesContentHoverWidget.ID, editor);
this._computer = new ModesContentComputer(this._editor);
this._highlightDecorations = [];
this._isChangingDecorations = false;
this._openerService = openerService || NullOpenerService;
this._modeService = modeService;
this._hoverOperation = new HoverOperation(
this._computer,
......@@ -244,13 +247,16 @@ export class ModesContentHoverWidget extends ContentHoverWidget {
actionCallback: (content) => {
this._openerService.open(URI.parse(content));
},
codeBlockRenderer: (modeId, value) => {
let mode: IMode;
let model = this._editor.getModel();
if (!model.isDisposed()) {
mode = model.getMode();
codeBlockRenderer: (modeId, value): string | TPromise<string> => {
let mode = this._modeService.getMode(modeId);
if (mode) {
return tokenizeToString(value, mode);
}
return tokenizeToString(value, model.getMode());
return this._modeService.getOrCreateMode(modeId).then(
mode => tokenizeToString(value, mode),
err => tokenizeToString(value, null));
}
}));
});
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册