diff --git a/packages/filesystem/src/node/download/file-download-endpoint.ts b/packages/filesystem/src/node/download/file-download-endpoint.ts index 6b66620847687..6066d28a0b47e 100644 --- a/packages/filesystem/src/node/download/file-download-endpoint.ts +++ b/packages/filesystem/src/node/download/file-download-endpoint.ts @@ -16,11 +16,13 @@ // tslint:disable:no-any +import * as url from 'url'; import { injectable, inject, named } from 'inversify'; import { json } from 'body-parser'; // tslint:disable-next-line:no-implicit-dependencies import { Application, Router } from 'express'; import { BackendApplicationContribution } from '@theia/core/lib/node/backend-application'; +import { FileUri } from '@theia/core/lib/node/file-uri'; import { FileDownloadHandler } from './file-download-handler'; @injectable() @@ -48,6 +50,15 @@ export class FileDownloadEndpoint implements BackendApplicationContribution { // Content-Type: application/json app.use(json()); app.use(FileDownloadEndpoint.PATH, router); + app.get('/file', (request, response) => { + const uri = url.parse(request.url).query; + if (!uri) { + response.status(400).send('invalid uri'); + return; + } + const fsPath = FileUri.fsPath(decodeURIComponent(uri)); + response.sendFile(fsPath); + }); } } diff --git a/packages/plugin-ext/src/main/browser/text-editors-main.ts b/packages/plugin-ext/src/main/browser/text-editors-main.ts index 11d49b15156cb..507332de9f264 100644 --- a/packages/plugin-ext/src/main/browser/text-editors-main.ts +++ b/packages/plugin-ext/src/main/browser/text-editors-main.ts @@ -14,6 +14,7 @@ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ +import URI from 'vscode-uri'; import { TextEditorsMain, MAIN_RPC_CONTEXT, @@ -25,6 +26,7 @@ import { ApplyEditsOptions, UndoStopOptions, DecorationRenderOptions, + ThemeDecorationInstanceRenderOptions, DecorationOptions, WorkspaceEditDto } from '../../common/plugin-api-rpc'; @@ -37,18 +39,21 @@ import { disposed } from '../../common/errors'; import { toMonacoWorkspaceEdit } from './languages-main'; import { MonacoBulkEditService } from '@theia/monaco/lib/browser/monaco-bulk-edit-service'; import { MonacoEditorService } from '@theia/monaco/lib/browser/monaco-editor-service'; +import { theiaUritoUriComponents, UriComponents } from '../../common/uri-components'; +import { Endpoint } from '@theia/core/lib/browser/endpoint'; export class TextEditorsMainImpl implements TextEditorsMain, Disposable { private readonly proxy: TextEditorsExt; private readonly toDispose = new DisposableCollection(); private readonly editorsToDispose = new Map(); + private readonly fileEndpoint = new Endpoint({ path: 'file' }).getRestUrl(); constructor( private readonly editorsAndDocuments: EditorsAndDocumentsMain, rpc: RPCProtocol, private readonly bulkEditService: MonacoBulkEditService, - private readonly monacoEditorService: MonacoEditorService + private readonly monacoEditorService: MonacoEditorService, ) { this.proxy = rpc.getProxy(MAIN_RPC_CONTEXT.TEXT_EDITORS_EXT); this.toDispose.push(editorsAndDocuments); @@ -127,10 +132,36 @@ export class TextEditorsMainImpl implements TextEditorsMain, Disposable { } $registerTextEditorDecorationType(key: string, options: DecorationRenderOptions): void { + this.injectRemoteUris(options); this.monacoEditorService.registerDecorationType(key, options); this.toDispose.push(Disposable.create(() => this.$removeTextEditorDecorationType(key))); } + protected injectRemoteUris(options: DecorationRenderOptions | ThemeDecorationInstanceRenderOptions): void { + if (options.before) { + options.before.contentIconPath = this.toRemoteUri(options.before.contentIconPath); + } + if (options.after) { + options.after.contentIconPath = this.toRemoteUri(options.after.contentIconPath); + } + if ('gutterIconPath' in options) { + options.gutterIconPath = this.toRemoteUri(options.gutterIconPath); + } + if ('dark' in options && options.dark) { + this.injectRemoteUris(options.dark); + } + if ('light' in options && options.light) { + this.injectRemoteUris(options.light); + } + } + + protected toRemoteUri(uri?: UriComponents): UriComponents | undefined { + if (uri && uri.scheme === 'file') { + return theiaUritoUriComponents(this.fileEndpoint.withQuery(URI.revive(uri).toString())); + } + return uri; + } + $removeTextEditorDecorationType(key: string): void { this.monacoEditorService.removeDecorationType(key); }