提交 2024296a 编写于 作者: J Johannes Rieken

first cut/experiment of icon/resouce loading, #75061

上级 d941578c
......@@ -29,6 +29,7 @@ import { IWorkspaceInitializationPayload } from 'vs/platform/workspaces/common/w
import { WorkspaceService } from 'vs/workbench/services/configuration/browser/configurationService';
import { ConfigurationCache } from 'vs/workbench/services/configuration/browser/configurationCache';
import { ConfigurationFileService } from 'vs/workbench/services/configuration/common/configuration';
import { WebResources } from 'vs/workbench/browser/web.resources';
interface IWindowConfiguration {
settingsUri: URI;
......@@ -61,6 +62,9 @@ class CodeRendererMain extends Disposable {
// Layout
this._register(addDisposableListener(window, EventType.RESIZE, () => this.workbench.layout()));
// Resource Loading
this._register(new WebResources(<IFileService>services.serviceCollection.get(IFileService)));
// Workbench Lifecycle
this._register(this.workbench.onShutdown(() => this.dispose()));
......@@ -188,4 +192,4 @@ function toResource(path: string): URI {
authority: document.location.host,
path
});
}
\ No newline at end of file
}
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IFileService } from 'vs/platform/files/common/files';
import { URI } from 'vs/base/common/uri';
export class WebResources {
private readonly _regexp = /url\(('|")?(vscode-remote:\/\/.*?)\1\)/g;
private readonly _cache = new Map<string, string>();
private readonly _observer: MutationObserver;
constructor(@IFileService private readonly _fileService: IFileService) {
this._observer = new MutationObserver(r => this._handleMutation(r));
// todo@joh add observer to more than head-element
// todo@joh explore alternative approach
this._observer.observe(document.head, { subtree: true, childList: true });
}
dispose(): void {
this._observer.disconnect();
this._cache.forEach(value => URL.revokeObjectURL(value));
}
private _handleMutation(records: MutationRecord[]): void {
for (const record of records) {
if (record.target.nodeName === 'STYLE') {
// style-element directly modified
this._handleStyleNode(record.target);
} else if (record.target.nodeName === 'HEAD' && record.type === 'childList') {
// style-element added to head
record.addedNodes.forEach(node => {
if (node.nodeName === 'STYLE') {
this._handleStyleNode(node);
}
});
}
}
}
private _handleStyleNode(target: Node): void {
if (!target.textContent) {
return;
}
const positions: number[] = [];
const promises: Promise<any>[] = [];
let match: RegExpMatchArray | null = null;
while (match = this._regexp.exec(target.textContent)) {
const remoteUrl = match[2];
positions.push(match.index! + 'url('.length + match[1].length);
positions.push(remoteUrl.length);
if (this._cache.has(remoteUrl)) {
promises.push(Promise.resolve());
} else {
promises.push(this._fileService.readFile(URI.parse(remoteUrl, true)).then(file => {
// todo@joh hack
const type = /\.woff$/.test(remoteUrl) ? 'application/font-woff' : 'image/svg+xml';
this._cache.set(remoteUrl, URL.createObjectURL(new Blob([file.value.buffer], { type })));
}));
}
}
if (promises.length === 0) {
return;
}
let content = target.textContent;
Promise.all(promises).then(() => {
if (target.textContent !== content) {
return;
}
for (let i = positions.length - 1; i >= 0; i -= 2) {
const start = positions[i - 1];
const len = positions[i];
const url = this._cache.get(content.substr(start, len));
content = content.substring(0, start) + url + content.substring(start + len);
}
target.textContent = content;
}).catch(e => {
console.error(e);
});
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册