diff --git a/src/vs/base/common/strings.ts b/src/vs/base/common/strings.ts index c629bfb92c07b..8b1cdf176b56b 100644 --- a/src/vs/base/common/strings.ts +++ b/src/vs/base/common/strings.ts @@ -48,6 +48,19 @@ export function format2(template: string, values: Record): stri return template.replace(_format2Regexp, (match, group) => (values[group] ?? match) as string); } +export function htmlAttributeEncodeValue(value: string): string { + return value.replace(/[<>"'&]/g, ch => { + switch (ch) { + case '<': return '<'; + case '>': return '>'; + case '"': return '"'; + case '\'': return '''; + case '&': return '&'; + } + return ch; + }); +} + /** * Converts HTML characters inside the string to use entities instead. Makes the string safe from * being used e.g. in HTMLElement.innerHTML. diff --git a/src/vs/editor/browser/viewParts/glyphMargin/glyphMargin.ts b/src/vs/editor/browser/viewParts/glyphMargin/glyphMargin.ts index 7323615254139..ff4739bb506b1 100644 --- a/src/vs/editor/browser/viewParts/glyphMargin/glyphMargin.ts +++ b/src/vs/editor/browser/viewParts/glyphMargin/glyphMargin.ts @@ -20,17 +20,17 @@ import { ViewContext } from 'vs/editor/common/viewModel/viewContext'; * This can end up producing multiple `LineDecorationToRender`. */ export class DecorationToRender { - _decorationToRenderBrand: void = undefined; + public readonly _decorationToRenderBrand: void = undefined; - public startLineNumber: number; - public endLineNumber: number; - public className: string; public readonly zIndex: number; - constructor(startLineNumber: number, endLineNumber: number, className: string, zIndex: number | undefined) { - this.startLineNumber = +startLineNumber; - this.endLineNumber = +endLineNumber; - this.className = String(className); + constructor( + public readonly startLineNumber: number, + public readonly endLineNumber: number, + public readonly className: string, + public readonly tooltip: string | null, + zIndex: number | undefined, + ) { this.zIndex = zIndex ?? 0; } } @@ -42,6 +42,7 @@ export class LineDecorationToRender { constructor( public readonly className: string, public readonly zIndex: number, + public readonly tooltip: string | null, ) { } } @@ -108,7 +109,7 @@ export abstract class DedupOverlay extends DynamicViewOverlay { } for (let i = startLineIndex; i <= prevEndLineIndex; i++) { - output[i].add(new LineDecorationToRender(className, zIndex)); + output[i].add(new LineDecorationToRender(className, zIndex, d.tooltip)); } } diff --git a/src/vs/editor/browser/viewParts/linesDecorations/linesDecorations.ts b/src/vs/editor/browser/viewParts/linesDecorations/linesDecorations.ts index 95d8caaed5123..9bbfeffae5764 100644 --- a/src/vs/editor/browser/viewParts/linesDecorations/linesDecorations.ts +++ b/src/vs/editor/browser/viewParts/linesDecorations/linesDecorations.ts @@ -78,11 +78,11 @@ export class LinesDecorationsOverlay extends DedupOverlay { const linesDecorationsClassName = d.options.linesDecorationsClassName; const zIndex = d.options.zIndex; if (linesDecorationsClassName) { - r[rLen++] = new DecorationToRender(d.range.startLineNumber, d.range.endLineNumber, linesDecorationsClassName, zIndex); + r[rLen++] = new DecorationToRender(d.range.startLineNumber, d.range.endLineNumber, linesDecorationsClassName, d.options.linesDecorationsTooltip ?? null, zIndex); } const firstLineDecorationClassName = d.options.firstLineDecorationClassName; if (firstLineDecorationClassName) { - r[rLen++] = new DecorationToRender(d.range.startLineNumber, d.range.startLineNumber, firstLineDecorationClassName, zIndex); + r[rLen++] = new DecorationToRender(d.range.startLineNumber, d.range.startLineNumber, firstLineDecorationClassName, d.options.linesDecorationsTooltip ?? null, zIndex); } } return r; @@ -103,7 +103,12 @@ export class LinesDecorationsOverlay extends DedupOverlay { const decorations = toRender[lineIndex].getDecorations(); let lineOutput = ''; for (const decoration of decorations) { - lineOutput += '