1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as DOM from 'vs/base/browser/dom';
import { Color } from 'vs/base/common/color';
import * as platform from 'vs/base/common/platform';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { EditorOption } from 'vs/editor/common/config/editorOptions';
import { Range } from 'vs/editor/common/core/range';
import * as languages from 'vs/editor/common/languages';
import { tokenizeLineToHTML } from 'vs/editor/common/languages/textToHtmlTokenizer';
import { ITextModel } from 'vs/editor/common/model';
import { BaseCellRenderTemplate } from 'vs/workbench/contrib/notebook/browser/view/notebookRenderingCommon';
class EditorTextRenderer {
private static _ttPolicy = window.trustedTypes?.createPolicy('cellRendererEditorText', {
createHTML(input) { return input; }
});
getRichText(editor: ICodeEditor, modelRange: Range): HTMLElement | null {
const model = editor.getModel();
if (!model) {
return null;
}
const colorMap = this.getDefaultColorMap();
const fontInfo = editor.getOptions().get(EditorOption.fontInfo);
const fontFamilyVar = '--notebook-editor-font-family';
const fontSizeVar = '--notebook-editor-font-size';
const fontWeightVar = '--notebook-editor-font-weight';
const style = ``
+ `color: ${colorMap[languages.ColorId.DefaultForeground]};`
+ `background-color: ${colorMap[languages.ColorId.DefaultBackground]};`
+ `font-family: var(${fontFamilyVar});`
+ `font-weight: var(${fontWeightVar});`
+ `font-size: var(${fontSizeVar});`
+ `line-height: ${fontInfo.lineHeight}px;`
+ `white-space: pre;`;
const element = DOM.$('div', { style });
const fontSize = fontInfo.fontSize;
const fontWeight = fontInfo.fontWeight;
element.style.setProperty(fontFamilyVar, fontInfo.fontFamily);
element.style.setProperty(fontSizeVar, `${fontSize}px`);
element.style.setProperty(fontWeightVar, fontWeight);
const linesHtml = this.getRichTextLinesAsHtml(model, modelRange, colorMap);
element.innerHTML = linesHtml as string;
return element;
}
private getRichTextLinesAsHtml(model: ITextModel, modelRange: Range, colorMap: string[]): string | TrustedHTML {
const startLineNumber = modelRange.startLineNumber;
const startColumn = modelRange.startColumn;
const endLineNumber = modelRange.endLineNumber;
const endColumn = modelRange.endColumn;
const tabSize = model.getOptions().tabSize;
let result = '';
for (let lineNumber = startLineNumber; lineNumber <= endLineNumber; lineNumber++) {
const lineTokens = model.tokenization.getLineTokens(lineNumber);
const lineContent = lineTokens.getLineContent();
const startOffset = (lineNumber === startLineNumber ? startColumn - 1 : 0);
const endOffset = (lineNumber === endLineNumber ? endColumn - 1 : lineContent.length);
if (lineContent === '') {
result += '<br>';
} else {
result += tokenizeLineToHTML(lineContent, lineTokens.inflate(), colorMap, startOffset, endOffset, tabSize, platform.isWindows);
}
}
return EditorTextRenderer._ttPolicy?.createHTML(result) ?? result;
}
private getDefaultColorMap(): string[] {
const colorMap = languages.TokenizationRegistry.getColorMap();
const result: string[] = ['#000000'];
if (colorMap) {
for (let i = 1, len = colorMap.length; i < len; i++) {
result[i] = Color.Format.CSS.formatHex(colorMap[i]);
}
}
return result;
}
}
export class CodeCellDragImageRenderer {
getDragImage(templateData: BaseCellRenderTemplate, editor: ICodeEditor, type: 'code' | 'markdown'): HTMLElement {
let dragImage = this.getDragImageImpl(templateData, editor, type);
if (!dragImage) {
// TODO@roblourens I don't think this can happen
dragImage = document.createElement('div');
dragImage.textContent = '1 cell';
}
return dragImage;
}
private getDragImageImpl(templateData: BaseCellRenderTemplate, editor: ICodeEditor, type: 'code' | 'markdown'): HTMLElement | null {
const dragImageContainer = templateData.container.cloneNode(true) as HTMLElement;
dragImageContainer.classList.forEach(c => dragImageContainer.classList.remove(c));
dragImageContainer.classList.add('cell-drag-image', 'monaco-list-row', 'focused', `${type}-cell-row`);
const editorContainer: HTMLElement | null = dragImageContainer.querySelector('.cell-editor-container');
if (!editorContainer) {
return null;
}
const richEditorText = new EditorTextRenderer().getRichText(editor, new Range(1, 1, 1, 1000));
if (!richEditorText) {
return null;
}
DOM.reset(editorContainer, richEditorText);
return dragImageContainer;
}
}
|