980becda8d
fixes #116341
187 lines
7.3 KiB
TypeScript
187 lines
7.3 KiB
TypeScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
import * as assert from 'assert';
|
|
import * as platform from 'vs/base/common/platform';
|
|
import { URI } from 'vs/base/common/uri';
|
|
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
|
import { CodeEditorServiceImpl, GlobalStyleSheet } from 'vs/editor/browser/services/codeEditorServiceImpl';
|
|
import { IDecorationRenderOptions } from 'vs/editor/common/editorCommon';
|
|
import { IResourceEditorInput } from 'vs/platform/editor/common/editor';
|
|
import { TestColorTheme, TestThemeService } from 'vs/platform/theme/test/common/testThemeService';
|
|
|
|
const themeServiceMock = new TestThemeService();
|
|
|
|
class TestCodeEditorServiceImpl extends CodeEditorServiceImpl {
|
|
getActiveCodeEditor(): ICodeEditor | null {
|
|
return null;
|
|
}
|
|
|
|
openCodeEditor(input: IResourceEditorInput, source: ICodeEditor | null, sideBySide?: boolean): Promise<ICodeEditor | null> {
|
|
return Promise.resolve(null);
|
|
}
|
|
}
|
|
|
|
class TestGlobalStyleSheet extends GlobalStyleSheet {
|
|
|
|
public rules: string[] = [];
|
|
|
|
constructor() {
|
|
super(null!);
|
|
}
|
|
|
|
public insertRule(rule: string, index?: number): void {
|
|
this.rules.unshift(rule);
|
|
}
|
|
|
|
public removeRulesContainingSelector(ruleName: string): void {
|
|
for (let i = 0; i < this.rules.length; i++) {
|
|
if (this.rules[i].indexOf(ruleName) >= 0) {
|
|
this.rules.splice(i, 1);
|
|
i--;
|
|
}
|
|
}
|
|
}
|
|
|
|
public read(): string {
|
|
return this.rules.join('\n');
|
|
}
|
|
}
|
|
|
|
suite('Decoration Render Options', () => {
|
|
let options: IDecorationRenderOptions = {
|
|
gutterIconPath: URI.parse('https://github.com/microsoft/vscode/blob/main/resources/linux/code.png'),
|
|
gutterIconSize: 'contain',
|
|
backgroundColor: 'red',
|
|
borderColor: 'yellow'
|
|
};
|
|
test('register and resolve decoration type', () => {
|
|
let s = new TestCodeEditorServiceImpl(themeServiceMock);
|
|
s.registerDecorationType('example', options);
|
|
assert.notStrictEqual(s.resolveDecorationOptions('example', false), undefined);
|
|
});
|
|
test('remove decoration type', () => {
|
|
let s = new TestCodeEditorServiceImpl(themeServiceMock);
|
|
s.registerDecorationType('example', options);
|
|
assert.notStrictEqual(s.resolveDecorationOptions('example', false), undefined);
|
|
s.removeDecorationType('example');
|
|
assert.throws(() => s.resolveDecorationOptions('example', false));
|
|
});
|
|
|
|
function readStyleSheet(styleSheet: TestGlobalStyleSheet): string {
|
|
return styleSheet.read();
|
|
}
|
|
|
|
test('css properties', () => {
|
|
const styleSheet = new TestGlobalStyleSheet();
|
|
const s = new TestCodeEditorServiceImpl(themeServiceMock, styleSheet);
|
|
s.registerDecorationType('example', options);
|
|
const sheet = readStyleSheet(styleSheet);
|
|
assert(sheet.indexOf(`{background:url('https://github.com/microsoft/vscode/blob/main/resources/linux/code.png') center center no-repeat;background-size:contain;}`) >= 0);
|
|
assert(sheet.indexOf(`{background-color:red;border-color:yellow;box-sizing: border-box;}`) >= 0);
|
|
});
|
|
|
|
test('theme color', () => {
|
|
const options: IDecorationRenderOptions = {
|
|
backgroundColor: { id: 'editorBackground' },
|
|
borderColor: { id: 'editorBorder' },
|
|
};
|
|
|
|
const styleSheet = new TestGlobalStyleSheet();
|
|
const themeService = new TestThemeService(new TestColorTheme({
|
|
editorBackground: '#FF0000'
|
|
}));
|
|
const s = new TestCodeEditorServiceImpl(themeService, styleSheet);
|
|
s.registerDecorationType('example', options);
|
|
assert.strictEqual(readStyleSheet(styleSheet), '.monaco-editor .ced-example-0 {background-color:#ff0000;border-color:transparent;box-sizing: border-box;}');
|
|
|
|
themeService.setTheme(new TestColorTheme({
|
|
editorBackground: '#EE0000',
|
|
editorBorder: '#00FFFF'
|
|
}));
|
|
assert.strictEqual(readStyleSheet(styleSheet), '.monaco-editor .ced-example-0 {background-color:#ee0000;border-color:#00ffff;box-sizing: border-box;}');
|
|
|
|
s.removeDecorationType('example');
|
|
assert.strictEqual(readStyleSheet(styleSheet), '');
|
|
});
|
|
|
|
test('theme overrides', () => {
|
|
const options: IDecorationRenderOptions = {
|
|
color: { id: 'editorBackground' },
|
|
light: {
|
|
color: '#FF00FF'
|
|
},
|
|
dark: {
|
|
color: '#000000',
|
|
after: {
|
|
color: { id: 'infoForeground' }
|
|
}
|
|
}
|
|
};
|
|
|
|
const styleSheet = new TestGlobalStyleSheet();
|
|
const themeService = new TestThemeService(new TestColorTheme({
|
|
editorBackground: '#FF0000',
|
|
infoForeground: '#444444'
|
|
}));
|
|
const s = new TestCodeEditorServiceImpl(themeService, styleSheet);
|
|
s.registerDecorationType('example', options);
|
|
const expected = [
|
|
'.vs-dark.monaco-editor .ced-example-4::after, .hc-black.monaco-editor .ced-example-4::after {color:#444444 !important;}',
|
|
'.vs-dark.monaco-editor .ced-example-1, .hc-black.monaco-editor .ced-example-1 {color:#000000 !important;}',
|
|
'.vs.monaco-editor .ced-example-1 {color:#FF00FF !important;}',
|
|
'.monaco-editor .ced-example-1 {color:#ff0000 !important;}'
|
|
].join('\n');
|
|
assert.strictEqual(readStyleSheet(styleSheet), expected);
|
|
|
|
s.removeDecorationType('example');
|
|
assert.strictEqual(readStyleSheet(styleSheet), '');
|
|
});
|
|
|
|
test('css properties, gutterIconPaths', () => {
|
|
const styleSheet = new TestGlobalStyleSheet();
|
|
const s = new TestCodeEditorServiceImpl(themeServiceMock, styleSheet);
|
|
|
|
// URI, only minimal encoding
|
|
s.registerDecorationType('example', { gutterIconPath: URI.parse('data:image/svg+xml;base64,PHN2ZyB4b+') });
|
|
assert(readStyleSheet(styleSheet).indexOf(`{background:url('data:image/svg+xml;base64,PHN2ZyB4b+') center center no-repeat;}`) > 0);
|
|
s.removeDecorationType('example');
|
|
|
|
function assertBackground(url1: string, url2: string) {
|
|
const actual = readStyleSheet(styleSheet);
|
|
assert(
|
|
actual.indexOf(`{background:url('${url1}') center center no-repeat;}`) > 0
|
|
|| actual.indexOf(`{background:url('${url2}') center center no-repeat;}`) > 0
|
|
);
|
|
}
|
|
|
|
if (platform.isWindows) {
|
|
// windows file path (used as string)
|
|
s.registerDecorationType('example', { gutterIconPath: URI.file('c:\\files\\miles\\more.png') });
|
|
assertBackground('file:///c:/files/miles/more.png', 'vscode-file://vscode-app/c:/files/miles/more.png');
|
|
s.removeDecorationType('example');
|
|
|
|
// single quote must always be escaped/encoded
|
|
s.registerDecorationType('example', { gutterIconPath: URI.file('c:\\files\\foo\\b\'ar.png') });
|
|
assertBackground('file:///c:/files/foo/b%27ar.png', 'vscode-file://vscode-app/c:/files/foo/b%27ar.png');
|
|
s.removeDecorationType('example');
|
|
} else {
|
|
// unix file path (used as string)
|
|
s.registerDecorationType('example', { gutterIconPath: URI.file('/Users/foo/bar.png') });
|
|
assertBackground('file:///Users/foo/bar.png', 'vscode-file://vscode-app/Users/foo/bar.png');
|
|
s.removeDecorationType('example');
|
|
|
|
// single quote must always be escaped/encoded
|
|
s.registerDecorationType('example', { gutterIconPath: URI.file('/Users/foo/b\'ar.png') });
|
|
assertBackground('file:///Users/foo/b%27ar.png', 'vscode-file://vscode-app/Users/foo/b%27ar.png');
|
|
s.removeDecorationType('example');
|
|
}
|
|
|
|
s.registerDecorationType('example', { gutterIconPath: URI.parse('http://test/pa\'th') });
|
|
assert(readStyleSheet(styleSheet).indexOf(`{background:url('http://test/pa%27th') center center no-repeat;}`) > 0);
|
|
s.removeDecorationType('example');
|
|
});
|
|
});
|