提交 51f2d539 编写于 作者: M Martin Aeschlimann

Use MarkedString insetad of HTMLContentElement

上级 8b60f07f
......@@ -40,7 +40,7 @@ declare module monaco {
#include(vs/base/common/cancellation): CancellationTokenSource, CancellationToken
#include(vs/base/common/uri): URI
#include(vs/base/common/keyCodes): KeyCode, KeyMod
#include(vs/base/common/htmlContent): IHTMLContentElementCode, IHTMLContentElement
#include(vs/base/common/htmlContent): MarkedString
#include(vs/base/browser/keyboardEvent): IKeyboardEvent
#include(vs/base/browser/mouseEvent): IMouseEvent
#include(vs/editor/common/editorCommon): IScrollEvent
......
......@@ -9,7 +9,7 @@ import DOM = require('vs/base/browser/dom');
import {defaultGenerator} from 'vs/base/common/idGenerator';
import {escape} from 'vs/base/common/strings';
import {TPromise} from 'vs/base/common/winjs.base';
import {IHTMLContentElement} from 'vs/base/common/htmlContent';
import {IHTMLContentElement, MarkedString} from 'vs/base/common/htmlContent';
import {marked} from 'vs/base/common/marked/marked';
import {IMouseEvent} from 'vs/base/browser/mouseEvent';
......@@ -20,6 +20,17 @@ export interface RenderOptions {
codeBlockRenderer?: (modeId: string, value: string) => string | TPromise<string>;
}
export function renderMarkedString(markedStrings: MarkedString[], options: RenderOptions = {}): Node {
let htmlContentElements = markedStrings.map(value => {
if (typeof value === 'string') {
return { markdown: value };
} else if (typeof value === 'object') {
return { code: value };
};
});
return renderHtml(htmlContentElements, options);
}
/**
* Create html nodes for the given content element.
*
......
......@@ -5,11 +5,73 @@
'use strict';
/**
* MarkedString can be used to render human readable text. It is either a markdown string
* or a code-block that provides a language and a code snippet. Note that
* markdown strings will be sanitized - that means html will be escaped.
*/
export type MarkedString = string | { language: string; value: string };
export interface IHTMLContentElementCode {
language: string;
value: string;
}
export function markedStringsEquals(a:MarkedString | MarkedString[], b:MarkedString |MarkedString[]): boolean {
if (!a && !b) {
return true;
}
if (!a || !b) {
return false;
}
if (Array.isArray(a)) {
if (!Array.isArray(b)) {
return false;
}
return markedStringArrEquals(<MarkedString[]> a, <MarkedString[]> b);
}
return markedStringEqual(<MarkedString> a, <MarkedString> b);
}
function markedStringArrEquals(a:MarkedString[], b:MarkedString[]): boolean {
let aLen = a.length,
bLen = b.length;
if (aLen !== bLen) {
return false;
}
for (let i = 0; i < aLen; i++) {
if (!markedStringEqual(a[i], b[i])) {
return false;
}
}
return true;
}
function markedStringEqual(a:MarkedString, b:MarkedString): boolean {
if (!a && !b) {
return true;
}
if (!a || !b) {
return false;
}
if (typeof a === 'string') {
return typeof b === 'string' && a === b;
}
return (
a['language'] === b['language']
&& a['value'] === b['value']
);
}
export function textToMarkedString(text: string) : MarkedString {
return { language: 'string', value: text };
}
export interface IHTMLContentElement {
/**
* supports **bold**, __italics__, and [[actions]]
......
......@@ -672,7 +672,7 @@ export abstract class CommonCodeEditor extends EventEmitter implements IActionPr
}
let opts = this._codeEditorService.resolveDecorationOptions(typeKey, !!decorationOption.hoverMessage);
if (decorationOption.hoverMessage) {
opts.htmlMessage = decorationOption.hoverMessage;
opts.hoverMessage = decorationOption.hoverMessage;
}
newModelDecorations.push({ range: decorationOption.range, options: opts });
}
......
......@@ -6,7 +6,7 @@
import {IAction} from 'vs/base/common/actions';
import {IEventEmitter, BulkListenerCallback} from 'vs/base/common/eventEmitter';
import {IHTMLContentElement} from 'vs/base/common/htmlContent';
import {MarkedString} from 'vs/base/common/htmlContent';
import URI from 'vs/base/common/uri';
import {TPromise} from 'vs/base/common/winjs.base';
import {IInstantiationService, IConstructorSignature1, IConstructorSignature2} from 'vs/platform/instantiation/common/instantiation';
......@@ -1022,13 +1022,14 @@ export interface IModelDecorationOptions {
*/
className?:string;
/**
* Message to be rendered when hovering over the decoration.
* Message to be rendered when hovering over the glyph margin decoration.
* @internal
*/
hoverMessage?:string;
glyphMarginHoverMessage?:string;
/**
* Array of IHTMLContentElements to render as the decoration message.
* Array of MarkedString to render as the decoration message.
*/
htmlMessage?:IHTMLContentElement[];
hoverMessage?:MarkedString | MarkedString[];
/**
* Should the decoration expand to encompass a whole line.
*/
......@@ -3768,7 +3769,7 @@ export interface IDecorationInstanceRenderOptions extends IThemeDecorationInstan
*/
export interface IDecorationOptions {
range: IRange;
hoverMessage?: IHTMLContentElement[];
hoverMessage?: MarkedString | MarkedString[];
renderOptions? : IDecorationInstanceRenderOptions;
}
......
......@@ -5,7 +5,7 @@
'use strict';
import {onUnexpectedError} from 'vs/base/common/errors';
import {IHTMLContentElement, htmlContentElementArrEquals} from 'vs/base/common/htmlContent';
import {MarkedString, markedStringsEquals} from 'vs/base/common/htmlContent';
import * as strings from 'vs/base/common/strings';
import {TPromise} from 'vs/base/common/winjs.base';
import {IdGenerator} from 'vs/base/common/idGenerator';
......@@ -646,8 +646,8 @@ class ModelDecorationOptions implements editorCommon.IModelDecorationOptions {
stickiness:editorCommon.TrackedRangeStickiness;
className:string;
hoverMessage:string;
htmlMessage:IHTMLContentElement[];
glyphMarginHoverMessage:string;
hoverMessage:MarkedString | MarkedString[];
isWholeLine:boolean;
showInOverviewRuler:string;
overviewRuler:editorCommon.IModelDecorationOverviewRulerOptions;
......@@ -660,8 +660,8 @@ class ModelDecorationOptions implements editorCommon.IModelDecorationOptions {
constructor(options:editorCommon.IModelDecorationOptions) {
this.stickiness = options.stickiness||editorCommon.TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges;
this.className = cleanClassName(options.className||strings.empty);
this.hoverMessage = options.hoverMessage||strings.empty;
this.htmlMessage = options.htmlMessage||[];
this.glyphMarginHoverMessage = options.glyphMarginHoverMessage||strings.empty;
this.hoverMessage = options.hoverMessage||[];
this.isWholeLine = options.isWholeLine||false;
this.overviewRuler = _normalizeOverviewRulerOptions(options.overviewRuler, options.showInOverviewRuler);
this.glyphMarginClassName = cleanClassName(options.glyphMarginClassName||strings.empty);
......@@ -683,7 +683,7 @@ class ModelDecorationOptions implements editorCommon.IModelDecorationOptions {
return (
this.stickiness === other.stickiness
&& this.className === other.className
&& this.hoverMessage === other.hoverMessage
&& this.glyphMarginHoverMessage === other.glyphMarginHoverMessage
&& this.isWholeLine === other.isWholeLine
&& this.showInOverviewRuler === other.showInOverviewRuler
&& this.glyphMarginClassName === other.glyphMarginClassName
......@@ -691,7 +691,7 @@ class ModelDecorationOptions implements editorCommon.IModelDecorationOptions {
&& this.inlineClassName === other.inlineClassName
&& this.beforeContentClassName === other.beforeContentClassName
&& this.afterContentClassName === other.afterContentClassName
&& htmlContentElementArrEquals(this.htmlMessage, other.htmlMessage)
&& markedStringsEquals(this.hoverMessage, other.hoverMessage)
&& ModelDecorationOptions._overviewRulerEquals(this.overviewRuler, other.overviewRuler)
);
}
......
......@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import {IHTMLContentElement} from 'vs/base/common/htmlContent';
import {MarkedString} from 'vs/base/common/htmlContent';
import {IDisposable} from 'vs/base/common/lifecycle';
import URI from 'vs/base/common/uri';
import {TPromise} from 'vs/base/common/winjs.base';
......@@ -321,7 +321,7 @@ export interface Hover {
/**
* The contents of this hover.
*/
htmlContent: IHTMLContentElement[];
contents: MarkedString[];
/**
* The range to which this hover applies. When missing, the
......
......@@ -8,7 +8,7 @@ import * as nls from 'vs/nls';
import {onUnexpectedError} from 'vs/base/common/errors';
import Event, {Emitter} from 'vs/base/common/event';
import {EmitterEvent} from 'vs/base/common/eventEmitter';
import {IHTMLContentElement} from 'vs/base/common/htmlContent';
import {MarkedString, textToMarkedString} from 'vs/base/common/htmlContent';
import {IDisposable} from 'vs/base/common/lifecycle';
import Severity from 'vs/base/common/severity';
import URI from 'vs/base/common/uri';
......@@ -127,7 +127,7 @@ class ModelMarkerHandler {
let className: string;
let color: string;
let darkColor: string;
let htmlMessage: IHTMLContentElement[] = null;
let htmlMessage: MarkedString[] = null;
switch (marker.severity) {
case Severity.Ignore:
......@@ -148,21 +148,21 @@ class ModelMarkerHandler {
}
if (typeof marker.message === 'string') {
htmlMessage = [{ isText: true, text: marker.message }];
htmlMessage = [ textToMarkedString(marker.message) ];
} else if (Array.isArray(marker.message)) {
htmlMessage = <IHTMLContentElement[]><any>marker.message;
htmlMessage = <MarkedString[]><any>marker.message;
} else if (marker.message) {
htmlMessage = [marker.message];
htmlMessage = [ marker.message ];
}
if (htmlMessage && marker.source) {
htmlMessage.unshift({ isText: true, text: `[${marker.source}] ` });
htmlMessage.unshift(`[${marker.source}] `);
}
return {
stickiness: editorCommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
className,
htmlMessage: htmlMessage,
hoverMessage: htmlMessage,
overviewRuler: {
color,
darkColor,
......
......@@ -8,7 +8,7 @@
import 'vs/css!./defineKeybinding';
import * as nls from 'vs/nls';
import {RunOnceScheduler} from 'vs/base/common/async';
import {IHTMLContentElement} from 'vs/base/common/htmlContent';
import {MarkedString} from 'vs/base/common/htmlContent';
import {CommonKeybindings, KeyCode, KeyMod, Keybinding} from 'vs/base/common/keyCodes';
import {IDisposable, dispose} from 'vs/base/common/lifecycle';
import {TPromise} from 'vs/base/common/winjs.base';
......@@ -175,27 +175,21 @@ export class DefineKeybindingController implements editorCommon.IEditorContribut
let newDecorations: editorCommon.IModelDeltaDecoration[] = [];
data.forEach((item) => {
let msg:IHTMLContentElement[];
let msg:MarkedString[];
let className: string;
let inlineClassName: string;
let overviewRulerColor: string;
if (!item.label) {
// this is the error case
msg = [{
tagName: 'span',
text: NLS_KB_LAYOUT_ERROR_MESSAGE
}];
msg = [NLS_KB_LAYOUT_ERROR_MESSAGE];
className = 'keybindingError';
inlineClassName = 'inlineKeybindingError';
overviewRulerColor = 'rgba(250, 100, 100, 0.6)';
} else {
// this is the info case
msg = [{
tagName: 'span',
text: NLS_KB_LAYOUT_INFO_MESSAGE
}];
msg = msg.concat(this._keybindingService.getHTMLLabelFor(item.keybinding));
msg = [NLS_KB_LAYOUT_INFO_MESSAGE];
msg = msg.concat(this._keybindingService.getLabelFor(item.keybinding));
className = 'keybindingInfo';
inlineClassName = 'inlineKeybindingInfo';
overviewRulerColor = 'rgba(100, 100, 250, 0.6)';
......@@ -216,7 +210,7 @@ export class DefineKeybindingController implements editorCommon.IEditorContribut
options: {
stickiness: editorCommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
className: className,
htmlMessage: msg,
hoverMessage: msg,
overviewRuler: {
color: overviewRulerColor,
darkColor: overviewRulerColor,
......
......@@ -9,7 +9,7 @@ import 'vs/css!./goToDeclaration';
import * as nls from 'vs/nls';
import {Throttler} from 'vs/base/common/async';
import {onUnexpectedError} from 'vs/base/common/errors';
import {IHTMLContentElement} from 'vs/base/common/htmlContent';
import {MarkedString, textToMarkedString} from 'vs/base/common/htmlContent';
import {KeyCode, KeyMod} from 'vs/base/common/keyCodes';
import * as platform from 'vs/base/common/platform';
import Severity from 'vs/base/common/severity';
......@@ -25,7 +25,6 @@ import {Behaviour} from 'vs/editor/common/editorActionEnablement';
import * as editorCommon from 'vs/editor/common/editorCommon';
import {CommonEditorRegistry, ContextKey, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions';
import {Location, DefinitionProviderRegistry} from 'vs/editor/common/modes';
import {tokenizeToHtmlContent} from 'vs/editor/common/modes/textToHtmlTokenizer';
import {ICodeEditor, IEditorMouseEvent, IMouseTarget} from 'vs/editor/browser/editorBrowser';
import {EditorBrowserRegistry} from 'vs/editor/browser/editorBrowserExtensions';
import {getDeclarationsAtPosition} from 'vs/editor/contrib/goToDeclaration/common/goToDeclaration';
......@@ -365,15 +364,17 @@ class GotoDefinitionWithMouseEditorContribution implements editorCommon.IEditorC
return;
}
let htmlMessage: IHTMLContentElement = {
tagName: 'div',
className: 'goto-definition-link-hover',
style: `tab-size: ${model.getOptions().tabSize}`
};
let htmlMessage: MarkedString = void 0;;
if (text && text.trim().length > 0) {
// not whitespace only
htmlMessage.children = [isCode ? tokenizeToHtmlContent(text, model.getMode()) : { tagName: 'span', text }];
if (isCode) {
htmlMessage = {
language: model.getMode().getId(),
value: text
};
console.log(htmlMessage);
} else {
htmlMessage = textToMarkedString(text);
}
}
let newDecorations = {
......
......@@ -8,7 +8,7 @@ import 'vs/css!vs/base/browser/ui/progressbar/progressbar';
import * as nls from 'vs/nls';
import URI from 'vs/base/common/uri';
import {TPromise} from 'vs/base/common/winjs.base';
import {renderHtml} from 'vs/base/browser/htmlContentRenderer';
import {renderMarkedString} 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';
......@@ -20,6 +20,7 @@ import {ICodeEditor} from 'vs/editor/browser/editorBrowser';
import {getHover} from '../common/hover';
import {HoverOperation, IHoverComputer} from './hoverOperation';
import {ContentHoverWidget} from './hoverWidgets';
import {textToMarkedString, MarkedString} from 'vs/base/common/htmlContent';
class ModesContentComputer implements IHoverComputer<Hover[]> {
......@@ -63,22 +64,27 @@ class ModesContentComputer implements IHoverComputer<Hover[]> {
return result;
}
var hasHoverContent = (contents: MarkedString | MarkedString[]) => {
return contents && (!Array.isArray(contents) || (<MarkedString[]> contents).length > 0);
};
var lineDecorations = this._editor.getLineDecorations(lineNumber);
var maxColumn = this._editor.getModel().getLineMaxColumn(lineNumber);
lineDecorations.forEach((d) => {
var startColumn = (d.range.startLineNumber === lineNumber) ? d.range.startColumn : 1;
var endColumn = (d.range.endLineNumber === lineNumber) ? d.range.endColumn : maxColumn;
if (startColumn <= this._range.startColumn && this._range.endColumn <= endColumn && (d.options.hoverMessage || (d.options.htmlMessage && d.options.htmlMessage.length > 0))) {
if (startColumn <= this._range.startColumn && this._range.endColumn <= endColumn && hasHoverContent(d.options.hoverMessage)) {
var obj:Hover = {
htmlContent: [],
contents: [],
range: new Range(this._range.startLineNumber, startColumn, this._range.startLineNumber, endColumn)
};
if (d.options.hoverMessage) {
obj.htmlContent.push({ text: d.options.hoverMessage });
}
if (d.options.htmlMessage) {
obj.htmlContent = obj.htmlContent.concat(d.options.htmlMessage);
if (Array.isArray(d.options.hoverMessage)) {
obj.contents = obj.contents.concat(<MarkedString[]> d.options.hoverMessage);
} else {
obj.contents.push(<MarkedString> d.options.hoverMessage);
}
}
result.push(obj);
}
......@@ -106,13 +112,7 @@ class ModesContentComputer implements IHoverComputer<Hover[]> {
private _getLoadingMessage(): Hover {
return {
range: this._range,
htmlContent: [{
tagName: 'div',
className: '',
children: [{
text: nls.localize('modesContentHover.loading', "Loading...")
}]
}]
contents: [textToMarkedString(nls.localize('modesContentHover.loading', "Loading..."))]
};
}
}
......@@ -241,25 +241,23 @@ export class ModesContentHoverWidget extends ContentHoverWidget {
var row:HTMLElement = document.createElement('div');
var container = row;
if (msg.htmlContent && msg.htmlContent.length > 0) {
msg.htmlContent.forEach((content) => {
container.appendChild(renderHtml(content, {
actionCallback: (content) => {
this._openerService.open(URI.parse(content));
},
codeBlockRenderer: (modeId, value): string | TPromise<string> => {
let mode = this._modeService.getMode(modeId);
if (mode) {
return tokenizeToString(value, mode);
}
return this._modeService.getOrCreateMode(modeId).then(
mode => tokenizeToString(value, mode),
err => tokenizeToString(value, null));
if (msg.contents && msg.contents.length > 0) {
container.appendChild(renderMarkedString(msg.contents, {
actionCallback: (content) => {
this._openerService.open(URI.parse(content));
},
codeBlockRenderer: (modeId, value): string | TPromise<string> => {
let mode = this._modeService.getMode(modeId);
if (mode) {
return tokenizeToString(value, mode);
}
}));
});
return this._modeService.getOrCreateMode(modeId).then(
mode => tokenizeToString(value, mode),
err => tokenizeToString(value, null));
}
}));
}
fragment.appendChild(row);
......
......@@ -45,9 +45,9 @@ class MarginComputer implements IHoverComputer<IHoverMessage[]> {
for (i = 0, len = lineDecorations.length; i < len; i++) {
d = lineDecorations[i];
if (d.options.glyphMarginClassName && d.options.hoverMessage) {
if (d.options.glyphMarginClassName && d.options.glyphMarginHoverMessage) {
result.push({
value: d.options.hoverMessage
value: d.options.glyphMarginHoverMessage
});
}
}
......
......@@ -25,7 +25,7 @@ export function getHover(model: IReadOnlyModel, position: Position): TPromise<Ho
}).then((result) => {
if (result) {
let hasRange = (typeof result.range !== 'undefined');
let hasHtmlContent = (typeof result.htmlContent !== 'undefined' && result.htmlContent && result.htmlContent.length > 0);
let hasHtmlContent = (typeof result.contents !== 'undefined' && result.contents && result.contents.length > 0);
if (hasRange && hasHtmlContent) {
values[idx] = result;
}
......
......@@ -576,9 +576,7 @@ suite('deltaDecorations', () => {
endColumn: 1
},
options: {
htmlMessage: [{
markdown: 'hello1'
}]
hoverMessage: ['hello1']
}
}]);
......@@ -590,15 +588,13 @@ suite('deltaDecorations', () => {
endColumn: 1
},
options: {
htmlMessage: [{
markdown: 'hello2'
}]
hoverMessage: ['hello2']
}
}]);
let actualDecoration = model.getDecorationOptions(ids[0]);
assert.equal(actualDecoration.htmlMessage[0].markdown, 'hello2');
assert.equal(actualDecoration.hoverMessage[0], 'hello2');
model.dispose();
});
......
......@@ -109,11 +109,11 @@ export class BowerJSONContribution implements JSONWorker.IJSONWorkerContribution
return null;
}
public getInfoContribution(resource: URI, location: JSONLocation): WinJS.TPromise<HtmlContent.IHTMLContentElement[]> {
public getInfoContribution(resource: URI, location: JSONLocation): WinJS.TPromise<HtmlContent.MarkedString[]> {
if (this.isBowerFile(resource) && (location.matches(['dependencies', '*']) || location.matches(['devDependencies', '*']))) {
var pack = location.getSegments()[location.getSegments().length - 1];
var htmlContent : HtmlContent.IHTMLContentElement[] = [];
htmlContent.push({className: 'type', text: nls.localize('json.bower.package.hover', '{0}', pack) });
var htmlContent : HtmlContent.MarkedString[] = [];
htmlContent.push(nls.localize('json.bower.package.hover', '{0}', pack));
var queryUrl = 'https://bower.herokuapp.com/packages/' + encodeURIComponent(pack);
......@@ -130,7 +130,7 @@ export class BowerJSONContribution implements JSONWorker.IJSONWorkerContribution
if (Strings.endsWith(url, '.git')) {
url = url.substring(0, url.length - 4);
}
htmlContent.push({className: 'documentation', text: url });
htmlContent.push(url);
}
} catch (e) {
// ignore
......
......@@ -60,7 +60,7 @@ export class GlobPatternContribution implements JSONWorker.IJSONWorkerContributi
return null;
}
public getInfoContribution(resource: URI, location: JSONLocation): WinJS.TPromise<HtmlContent.IHTMLContentElement[]> {
public getInfoContribution(resource: URI, location: JSONLocation): WinJS.TPromise<HtmlContent.MarkedString[]> {
return null;
}
}
\ No newline at end of file
......@@ -139,12 +139,12 @@ export class PackageJSONContribution implements JSONWorker.IJSONWorkerContributi
return null;
}
public getInfoContribution(resource: URI, location: JSONLocation): WinJS.TPromise<HtmlContent.IHTMLContentElement[]> {
public getInfoContribution(resource: URI, location: JSONLocation): WinJS.TPromise<HtmlContent.MarkedString[]> {
if (this.isPackageJSONFile(resource) && (location.matches(['dependencies', '*']) || location.matches(['devDependencies', '*']) || location.matches(['optionalDependencies', '*']) || location.matches(['peerDependencies', '*']))) {
var pack = location.getSegments()[location.getSegments().length - 1];
var htmlContent : HtmlContent.IHTMLContentElement[] = [];
htmlContent.push({className: 'type', text: nls.localize('json.npm.package.hover', '{0}', pack) });
var htmlContent : HtmlContent.MarkedString[] = [];
htmlContent.push(nls.localize('json.npm.package.hover', '{0}', pack));
var queryUrl = 'http://registry.npmjs.org/' + encodeURIComponent(pack) + '/latest';
......@@ -155,10 +155,10 @@ export class PackageJSONContribution implements JSONWorker.IJSONWorkerContributi
var obj = JSON.parse(success.responseText);
if (obj) {
if (obj.description) {
htmlContent.push({className: 'documentation', text: obj.description });
htmlContent.push(obj.description);
}
if (obj.version) {
htmlContent.push({className: 'documentation', text: nls.localize('json.npm.version.hover', 'Latest version: {0}', obj.version) });
htmlContent.push(nls.localize('json.npm.version.hover', 'Latest version: {0}', obj.version));
}
}
} catch (e) {
......
......@@ -148,12 +148,12 @@ export class ProjectJSONContribution implements JSONWorker.IJSONWorkerContributi
return null;
}
public getInfoContribution(resource: URI, location: JSONLocation): WinJS.TPromise<HtmlContent.IHTMLContentElement[]> {
public getInfoContribution(resource: URI, location: JSONLocation): WinJS.TPromise<HtmlContent.MarkedString[]> {
if (this.isProjectJSONFile(resource) && (location.matches(['dependencies', '*']) || location.matches(['frameworks', '*', 'dependencies', '*']) || location.matches(['frameworks', '*', 'frameworkAssemblies', '*']))) {
var pack = location.getSegments()[location.getSegments().length - 1];
var htmlContent : HtmlContent.IHTMLContentElement[] = [];
htmlContent.push({className: 'type', text: nls.localize('json.nugget.package.hover', '{0}', pack) });
var htmlContent : HtmlContent.MarkedString[] = [];
htmlContent.push(nls.localize('json.nugget.package.hover', '{0}', pack));
var queryUrl = 'https://www.myget.org/F/aspnetrelease/api/v2/Packages?'
+ '$filter=Id%20eq%20\''
......@@ -171,10 +171,10 @@ export class ProjectJSONContribution implements JSONWorker.IJSONWorkerContributi
if (obj.d && obj.d[0]) {
var res = obj.d[0];
if (res.Description) {
htmlContent.push({className: 'documentation', text: res.Description });
htmlContent.push(res.Description);
}
if (res.Version) {
htmlContent.push({className: 'documentation', text: nls.localize('json.nugget.version.hover', 'Latest version: {0}', res.Version) });
htmlContent.push(nls.localize('json.nugget.version.hover', 'Latest version: {0}', res.Version));
}
}
} catch (e) {
......
......@@ -62,7 +62,7 @@ export interface ISuggestionsCollector {
}
export interface IJSONWorkerContribution {
getInfoContribution(resource: URI, location: JSONLocation) : WinJS.TPromise<HtmlContent.IHTMLContentElement[]>;
getInfoContribution(resource: URI, location: JSONLocation) : WinJS.TPromise<HtmlContent.MarkedString[]>;
collectPropertySuggestions(resource: URI, location: JSONLocation, currentWord: string, addValue: boolean, isLast:boolean, result: ISuggestionsCollector) : WinJS.Promise;
collectValueSuggestions(resource: URI, location: JSONLocation, propertyKey: string, result: ISuggestionsCollector): WinJS.Promise;
collectDefaultSuggestions(resource: URI, result: ISuggestionsCollector): WinJS.Promise;
......@@ -325,7 +325,7 @@ export class JSONWorker {
}
if (description) {
var htmlContent = [ {className: 'documentation', text: description } ];
var htmlContent = [ description ];
return this.createInfoResult(htmlContent, originalNode, modelMirror);
}
}
......@@ -333,11 +333,11 @@ export class JSONWorker {
});
}
private createInfoResult(htmlContent : HtmlContent.IHTMLContentElement[], node: Parser.ASTNode, modelMirror: EditorCommon.IMirrorModel) : Modes.Hover {
private createInfoResult(htmlContent : HtmlContent.MarkedString[], node: Parser.ASTNode, modelMirror: EditorCommon.IMirrorModel) : Modes.Hover {
var range = modelMirror.getRangeFromOffsetAndLength(node.start, node.end - node.start);
var result:Modes.Hover = {
htmlContent: htmlContent,
contents: htmlContent,
range: range
};
return result;
......
......@@ -603,35 +603,23 @@ suite('JSON - Worker', () => {
};
WinJS.Promise.join([
testComputeInfo(content, schema, {lineNumber:1, column:1}).then((result) => {
assert.deepEqual(result.htmlContent, [
{
className: 'documentation',
text: 'a very special object'
}
assert.deepEqual(result.contents, [
'a very special object'
]);
}),
testComputeInfo(content, schema, {lineNumber: 1, column: 2}).then((result) => {
assert.deepEqual(result.htmlContent, [
{
className: 'documentation',
text: 'A'
}
assert.deepEqual(result.contents, [
'A'
]);
}),
testComputeInfo(content, schema, {lineNumber:1, column:33}).then((result) => {
assert.deepEqual(result.htmlContent, [
{
className: 'documentation',
text: 'C'
}
assert.deepEqual(result.contents, [
'C'
]);
}),
testComputeInfo(content, schema, {lineNumber:1, column:8}).then((result) => {
assert.deepEqual(result.htmlContent, [
{
className: 'documentation',
text: 'A'
}
assert.deepEqual(result.contents, [
'A'
]);
})
]).done(() => testDone(), (errors:any[]) => {
......@@ -662,19 +650,13 @@ suite('JSON - Worker', () => {
};
WinJS.Promise.join([
testComputeInfo(content, schema, {lineNumber:1, column:10}).then((result) => {
assert.deepEqual(result.htmlContent, [
{
className: 'documentation',
text: 'a very special object'
}
assert.deepEqual(result.contents, [
'a very special object'
]);
}),
testComputeInfo(content, schema, {lineNumber:1, column:2}).then((result) => {
assert.deepEqual(result.htmlContent, [
{
className: 'documentation',
text: 'A'
}
assert.deepEqual(result.contents, [
'A'
]);
})
]).done(() => testDone(), (errors:any[]) => {
......
......@@ -347,27 +347,15 @@ declare module monaco {
static WinCtrl: number;
static chord(firstPart: number, secondPart: number): number;
}
export interface IHTMLContentElementCode {
/**
* MarkedString can be used to render human readable text. It is either a markdown string
* or a code-block that provides a language and a code snippet. Note that
* markdown strings will be sanitized - that means html will be escaped.
*/
export type MarkedString = string | {
language: string;
value: string;
}
export interface IHTMLContentElement {
/**
* supports **bold**, __italics__, and [[actions]]
*/
formattedText?: string;
text?: string;
className?: string;
style?: string;
customStyle?: any;
tagName?: string;
children?: IHTMLContentElement[];
isText?: boolean;
role?: string;
markdown?: string;
code?: IHTMLContentElementCode;
}
};
export interface IKeyboardEvent {
browserEvent: KeyboardEvent;
......@@ -1498,13 +1486,9 @@ declare module monaco.editor {
*/
className?: string;
/**
* Message to be rendered when hovering over the decoration.
*/
hoverMessage?: string;
/**
* Array of IHTMLContentElements to render as the decoration message.
* Array of MarkedString to render as the decoration message.
*/
htmlMessage?: IHTMLContentElement[];
hoverMessage?: MarkedString | MarkedString[];
/**
* Should the decoration expand to encompass a whole line.
*/
......@@ -4168,7 +4152,7 @@ declare module monaco.languages {
/**
* The contents of this hover.
*/
htmlContent: IHTMLContentElement[];
contents: MarkedString[];
/**
* The range to which this hover applies. When missing, the
* editor will use the range at the current position or the
......
......@@ -12,7 +12,6 @@ import * as modes from 'vs/editor/common/modes';
import * as types from './extHostTypes';
import {Position as EditorPosition} from 'vs/platform/editor/common/editor';
import {IPosition, ISelection, IRange, IDecorationOptions, ISingleEditOperation} from 'vs/editor/common/editorCommon';
import {IHTMLContentElement} from 'vs/base/common/htmlContent';
import {ITypeBearing} from 'vs/workbench/parts/search/common/search';
import * as vscode from 'vscode';
import URI from 'vs/base/common/uri';
......@@ -125,36 +124,6 @@ export function toViewColumn(position?: EditorPosition): vscode.ViewColumn {
}
}
export function fromFormattedString(value: vscode.MarkedString): IHTMLContentElement {
if (typeof value === 'string') {
return { markdown: value };
} else if (typeof value === 'object') {
return { code: value };
}
}
export function toFormattedString(value: IHTMLContentElement): vscode.MarkedString {
if (typeof value.code === 'string') {
return value.code;
}
let {markdown, text} = value;
return markdown || text || '<???>';
}
function isMarkedStringArr(something: vscode.MarkedString | vscode.MarkedString[]): something is vscode.MarkedString[] {
return Array.isArray(something);
}
function fromMarkedStringOrMarkedStringArr(something: vscode.MarkedString | vscode.MarkedString[]): IHTMLContentElement[] {
if (isMarkedStringArr(something)) {
return something.map(msg => fromFormattedString(msg));
} else if (something) {
return [fromFormattedString(something)];
} else {
return [];
}
}
function isDecorationOptions(something: any): something is vscode.DecorationOptions {
return (typeof something.range !== 'undefined');
}
......@@ -171,7 +140,7 @@ export function fromRangeOrRangeWithMessage(ranges:vscode.Range[]|vscode.Decorat
return ranges.map((r): IDecorationOptions => {
return {
range: fromRange(r.range),
hoverMessage: fromMarkedStringOrMarkedStringArr(r.hoverMessage),
hoverMessage: r.hoverMessage,
renderOptions: r.renderOptions
};
});
......@@ -256,12 +225,12 @@ export const location = {
export function fromHover(hover: vscode.Hover): modes.Hover {
return <modes.Hover>{
range: fromRange(hover.range),
htmlContent: hover.contents.map(fromFormattedString)
contents: hover.contents
};
}
export function toHover(info: modes.Hover): types.Hover {
return new types.Hover(info.htmlContent.map(toFormattedString), toRange(info.range));
return new types.Hover(info.contents, toRange(info.range));
}
export function toDocumentHighlight(occurrence: modes.DocumentHighlight): types.DocumentHighlight {
......
......@@ -284,13 +284,13 @@ export class DebugEditorModelManager implements IWorkbenchContribution {
if (result && breakpoint.message) {
result = objects.clone(result);
result.hoverMessage = breakpoint.message;
result.glyphMarginHoverMessage = breakpoint.message;
}
return result ? result :
!session || session.configuration.capabilities.supportsConditionalBreakpoints ? {
glyphMarginClassName: 'debug-breakpoint-conditional-glyph',
hoverMessage: breakpoint.condition,
glyphMarginHoverMessage: breakpoint.condition,
stickiness: editorcommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges
} : DebugEditorModelManager.BREAKPOINT_UNSUPPORTED_DECORATION;
}
......@@ -299,31 +299,31 @@ export class DebugEditorModelManager implements IWorkbenchContribution {
private static BREAKPOINT_DECORATION: editorcommon.IModelDecorationOptions = {
glyphMarginClassName: 'debug-breakpoint-glyph',
hoverMessage: nls.localize('breakpointHover', "Breakpoint"),
glyphMarginHoverMessage: nls.localize('breakpointHover', "Breakpoint"),
stickiness: editorcommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges
};
private static BREAKPOINT_DISABLED_DECORATION: editorcommon.IModelDecorationOptions = {
glyphMarginClassName: 'debug-breakpoint-disabled-glyph',
hoverMessage: nls.localize('breakpointDisabledHover', "Disabled Breakpoint"),
glyphMarginHoverMessage: nls.localize('breakpointDisabledHover', "Disabled Breakpoint"),
stickiness: editorcommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges
};
private static BREAKPOINT_UNVERIFIED_DECORATION: editorcommon.IModelDecorationOptions = {
glyphMarginClassName: 'debug-breakpoint-unverified-glyph',
hoverMessage: nls.localize('breakpointUnverifieddHover', "Unverified Breakpoint"),
glyphMarginHoverMessage: nls.localize('breakpointUnverifieddHover', "Unverified Breakpoint"),
stickiness: editorcommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges
};
private static BREAKPOINT_DIRTY_DECORATION: editorcommon.IModelDecorationOptions = {
glyphMarginClassName: 'debug-breakpoint-unverified-glyph',
hoverMessage: nls.localize('breakpointDirtydHover', "Unverified breakpoint. File is modified, please restart debug session."),
glyphMarginHoverMessage: nls.localize('breakpointDirtydHover', "Unverified breakpoint. File is modified, please restart debug session."),
stickiness: editorcommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges
};
private static BREAKPOINT_UNSUPPORTED_DECORATION: editorcommon.IModelDecorationOptions = {
glyphMarginClassName: 'debug-breakpoint-unsupported-glyph',
hoverMessage: nls.localize('breakpointUnsupported', "Conditional breakpoints not supported by this debug type"),
glyphMarginHoverMessage: nls.localize('breakpointUnsupported', "Conditional breakpoints not supported by this debug type"),
stickiness: editorcommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges
};
......
......@@ -383,8 +383,8 @@ suite('ExtHostLanguageFeatures', function() {
return getHover(model, new EditorPosition(1, 1)).then(value => {
assert.equal(value.length, 2);
let [first, second] = value;
assert.equal(first.htmlContent[0].markdown, 'registered second');
assert.equal(second.htmlContent[0].markdown, 'registered first');
assert.equal(first.contents[0], 'registered second');
assert.equal(second.contents[0], 'registered first');
});
});
});
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册