mirror of https://github.com/opensumi/core
feat: support monaco editor worker (#3703)
This commit is contained in:
parent
0aa3838b84
commit
f5cedc4cf4
|
@ -8,6 +8,7 @@ node_modules
|
|||
**/tools/playwright/lib/**
|
||||
**/tools/cli-engine/lib/**
|
||||
tools/cli-engine/src/browser/worker-host.js
|
||||
packages/monaco/worker/**
|
||||
|
||||
**/typings/**
|
||||
**/scripts/**
|
||||
|
|
|
@ -8,6 +8,9 @@ on:
|
|||
required: true
|
||||
default: 'main'
|
||||
|
||||
env:
|
||||
NODE_ENV: production
|
||||
|
||||
jobs:
|
||||
rc-version:
|
||||
name: RC Version
|
||||
|
|
|
@ -12,6 +12,9 @@ on:
|
|||
description: 'The release branch, eg: v3.xx, main'
|
||||
required: false
|
||||
|
||||
env:
|
||||
NODE_ENV: production
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: Release
|
||||
|
|
|
@ -4,6 +4,7 @@ node_modules
|
|||
**/tools/extensions/**
|
||||
**/tools/**/vendor/
|
||||
tools/cli-engine/src/browser/worker-host.js
|
||||
packages/monaco/worker/**
|
||||
|
||||
**/typings/**
|
||||
packages/*/lib/**
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"license": "MIT",
|
||||
"scripts": {
|
||||
"preinstall": "node scripts/preinstall.js && husky install",
|
||||
"clean": "rimraf \"./packages/*/lib\"",
|
||||
"clean": "rimraf \"./packages/*/lib\" && lerna run clean",
|
||||
"check:dep": "tsx ./scripts/depcheck",
|
||||
"init": "yarn run clean && yarn run build:all",
|
||||
"start": "yarn run rebuild:node && cross-env HOST=127.0.0.1 WS_PATH=ws://127.0.0.1:8000 NODE_ENV=development tsx ./scripts/start",
|
||||
|
@ -19,11 +19,12 @@
|
|||
"add:node": "tsx ./scripts/add-node",
|
||||
"add:browser": "tsx ./scripts/add-browser",
|
||||
"build": "yarn run compile",
|
||||
"build:all": "yarn run build && yarn run build:worker-host && yarn run build:ext-host && yarn run build:components",
|
||||
"build:all": "yarn run build && yarn run build:worker-host && yarn run build:ext-host && yarn run build:components && yarn build:monaco-worker",
|
||||
"compile": "cross-env NODE_ENV=production tsx ./scripts/build",
|
||||
"build:worker-host": "cd packages/extension && yarn run compile:worker",
|
||||
"build:ext-host": "cd packages/extension && yarn run build:ext-host",
|
||||
"build:cli-engine": "cd tools/cli-engine && yarn run build",
|
||||
"build:monaco-worker": "cd packages/monaco && yarn run build:worker",
|
||||
"watch:ext-host": "cd packages/extension && yarn run watch:ext-host",
|
||||
"watch:worker-host": "cd packages/extension && yarn run watch:worker",
|
||||
"watch": "yarn run rebuild:node && cross-env NODE_ENV=production tsx ./scripts/watch",
|
||||
|
@ -133,7 +134,8 @@
|
|||
"tslib": "^2.6.2",
|
||||
"tsx": "^4.7.1",
|
||||
"typescript": "4.9.3",
|
||||
"webpack": "^5.90.0"
|
||||
"webpack": "^5.90.0",
|
||||
"webpack-manifest-plugin": "^5.0.0"
|
||||
},
|
||||
"workspaces": [
|
||||
"packages/*",
|
||||
|
|
|
@ -4,12 +4,12 @@ import { Injector } from '@opensumi/di';
|
|||
import { LanguageParserService } from '@opensumi/ide-ai-native/lib/browser/languages/service';
|
||||
import { AppConfig, BrowserModule } from '@opensumi/ide-core-browser';
|
||||
import { ESupportRuntime } from '@opensumi/ide-core-browser/lib/application/runtime';
|
||||
import { IRendererRuntime } from '@opensumi/ide-core-browser/lib/application/runtime/types';
|
||||
import { RendererRuntime } from '@opensumi/ide-core-browser/lib/application/runtime/types';
|
||||
import { Uri } from '@opensumi/ide-core-common';
|
||||
import { MockInjector } from '@opensumi/ide-dev-tool/src/mock-injector';
|
||||
|
||||
class MockRendererRuntime implements IRendererRuntime {
|
||||
runtimeName: ESupportRuntime;
|
||||
class MockRendererRuntime extends RendererRuntime {
|
||||
runtimeName = 'web' as ESupportRuntime;
|
||||
mergeAppConfig(meta: AppConfig): AppConfig {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ describe.skip('tree sitter', () => {
|
|||
useClass: LanguageParserService,
|
||||
},
|
||||
]);
|
||||
injector.mockService(IRendererRuntime, new MockRendererRuntime());
|
||||
injector.mockService(RendererRuntime, new MockRendererRuntime());
|
||||
});
|
||||
|
||||
it('parser', async () => {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import Parser from 'web-tree-sitter';
|
||||
|
||||
import { Autowired, Injectable } from '@opensumi/di';
|
||||
import { EKnownResources, IRendererRuntime } from '@opensumi/ide-core-browser/lib/application/runtime/types';
|
||||
import { EKnownResources, RendererRuntime } from '@opensumi/ide-core-browser/lib/application/runtime/types';
|
||||
import { Deferred } from '@opensumi/ide-utils';
|
||||
|
||||
/**
|
||||
|
@ -13,8 +13,8 @@ export class WasmModuleManager {
|
|||
|
||||
private cachedRuntime: Map<string, Deferred<ArrayBuffer>> = new Map();
|
||||
|
||||
@Autowired(IRendererRuntime)
|
||||
rendererRuntime: IRendererRuntime;
|
||||
@Autowired(RendererRuntime)
|
||||
rendererRuntime: RendererRuntime;
|
||||
|
||||
private async resolveResourceUri() {
|
||||
const uri = await this.rendererRuntime.provideResourceUri(EKnownResources.TreeSitterWasmDirectory);
|
||||
|
|
|
@ -1,38 +1,19 @@
|
|||
import { Autowired, Injectable, Injector } from '@opensumi/di';
|
||||
import { Injectable, Injector } from '@opensumi/di';
|
||||
|
||||
import { BrowserModule } from '../../../browser-module';
|
||||
import { AppConfig } from '../../../react-providers';
|
||||
import { ESupportRuntime, onigWasmCDNUri, treeSitterWasmCDNUri } from '../constants';
|
||||
import { EKnownResources, IRendererRuntime } from '../types';
|
||||
import { ESupportRuntime } from '../constants';
|
||||
import { RendererRuntime } from '../types';
|
||||
|
||||
import { injectBrowserInnerProviders } from './inner-providers-browser';
|
||||
|
||||
@Injectable()
|
||||
export class BrowserRuntime implements IRendererRuntime {
|
||||
export class BrowserRuntime extends RendererRuntime {
|
||||
runtimeName = ESupportRuntime.Web;
|
||||
|
||||
@Autowired(AppConfig)
|
||||
appConfig: AppConfig;
|
||||
|
||||
registerRuntimeModuleProviders(injector: Injector, instance: BrowserModule<any>): void {
|
||||
instance.webProviders && injector.addProviders(...instance.webProviders);
|
||||
}
|
||||
registerRuntimeInnerProviders(injector: Injector): void {
|
||||
injectBrowserInnerProviders(injector);
|
||||
}
|
||||
|
||||
mergeAppConfig(meta: AppConfig): AppConfig {
|
||||
return meta;
|
||||
}
|
||||
|
||||
async provideResourceUri(resource: EKnownResources): Promise<string> {
|
||||
switch (resource) {
|
||||
case EKnownResources.OnigWasm:
|
||||
return this.appConfig.onigWasmUri || onigWasmCDNUri;
|
||||
case EKnownResources.TreeSitterWasmDirectory:
|
||||
return this.appConfig.treeSitterWasmDirectoryUri || treeSitterWasmCDNUri;
|
||||
default:
|
||||
throw new Error(`Unknown resource: ${resource}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,15 @@
|
|||
import { Autowired, Injectable, Injector } from '@opensumi/di';
|
||||
import { Injectable, Injector } from '@opensumi/di';
|
||||
|
||||
import { BrowserModule } from '../../../browser-module';
|
||||
import { AppConfig } from '../../../react-providers';
|
||||
import { electronEnv } from '../../../utils/electron';
|
||||
import { ESupportRuntime, onigWasmCDNUri, treeSitterWasmCDNUri } from '../constants';
|
||||
import { EKnownResources, IRendererRuntime } from '../types';
|
||||
import { EKnownResources, RendererRuntime } from '../types';
|
||||
|
||||
import { injectElectronInnerProviders } from './inner-providers-electron';
|
||||
|
||||
@Injectable()
|
||||
export class ElectronRendererRuntime implements IRendererRuntime {
|
||||
@Autowired(AppConfig)
|
||||
appConfig: AppConfig;
|
||||
|
||||
export class ElectronRendererRuntime extends RendererRuntime {
|
||||
runtimeName = ESupportRuntime.Electron;
|
||||
|
||||
registerRuntimeModuleProviders(injector: Injector, instance: BrowserModule<any>): void {
|
||||
|
@ -21,11 +18,12 @@ export class ElectronRendererRuntime implements IRendererRuntime {
|
|||
registerRuntimeInnerProviders(injector: Injector): void {
|
||||
injectElectronInnerProviders(injector);
|
||||
}
|
||||
mergeAppConfig(meta: AppConfig): AppConfig {
|
||||
|
||||
override mergeAppConfig(meta: AppConfig): AppConfig {
|
||||
return mergeElectronMetadata(meta);
|
||||
}
|
||||
|
||||
async provideResourceUri(resource: EKnownResources): Promise<string> {
|
||||
override async provideResourceUri(resource: EKnownResources): Promise<string> {
|
||||
switch (resource) {
|
||||
case EKnownResources.OnigWasm:
|
||||
return electronEnv.onigWasmUri || this.appConfig.onigWasmUri || onigWasmCDNUri;
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
import type { ESupportRuntime } from './constants';
|
||||
import { Autowired, Injectable } from '@opensumi/di';
|
||||
|
||||
import { AppConfig } from '../../react-providers/config-provider';
|
||||
|
||||
import { type ESupportRuntime, onigWasmCDNUri, treeSitterWasmCDNUri } from './constants';
|
||||
|
||||
import type { BrowserModule } from '../../browser-module';
|
||||
import type { AppConfig } from '../../react-providers/config-provider';
|
||||
import type { Injector } from '@opensumi/di';
|
||||
|
||||
export enum EKnownResources {
|
||||
|
@ -8,13 +12,28 @@ export enum EKnownResources {
|
|||
TreeSitterWasmDirectory = 'wasm:tree-sitter',
|
||||
}
|
||||
|
||||
export const IRendererRuntime = Symbol('IRendererRuntime');
|
||||
export interface IRendererRuntime {
|
||||
runtimeName: ESupportRuntime;
|
||||
@Injectable()
|
||||
export abstract class RendererRuntime {
|
||||
@Autowired(AppConfig)
|
||||
protected appConfig: AppConfig;
|
||||
|
||||
mergeAppConfig(meta: AppConfig): AppConfig;
|
||||
registerRuntimeInnerProviders(injector: Injector): void;
|
||||
registerRuntimeModuleProviders(injector: Injector, module: BrowserModule): void;
|
||||
abstract runtimeName: ESupportRuntime;
|
||||
|
||||
provideResourceUri(resource: EKnownResources): Promise<string>;
|
||||
abstract registerRuntimeInnerProviders(injector: Injector): void;
|
||||
abstract registerRuntimeModuleProviders(injector: Injector, module: BrowserModule): void;
|
||||
|
||||
mergeAppConfig(meta: AppConfig): AppConfig {
|
||||
return meta;
|
||||
}
|
||||
|
||||
async provideResourceUri(resource: string): Promise<string> {
|
||||
switch (resource) {
|
||||
case EKnownResources.OnigWasm:
|
||||
return this.appConfig.onigWasmUri || onigWasmCDNUri;
|
||||
case EKnownResources.TreeSitterWasmDirectory:
|
||||
return this.appConfig.treeSitterWasmDirectoryUri || treeSitterWasmCDNUri;
|
||||
default:
|
||||
throw new Error(`Unknown resource: ${resource}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import {
|
|||
StorageProvider,
|
||||
StorageResolverContribution,
|
||||
SupportLogNamespace,
|
||||
URI,
|
||||
UrlProvider,
|
||||
asExtensionCandidate,
|
||||
createContributionProvider,
|
||||
|
@ -49,7 +50,7 @@ import { ESupportRuntime, ElectronConnectionHelper, WebConnectionHelper } from '
|
|||
import { CONNECTION_HELPER_TOKEN } from '../application/runtime/base-socket';
|
||||
import { BrowserRuntime } from '../application/runtime/browser';
|
||||
import { ElectronRendererRuntime } from '../application/runtime/electron-renderer';
|
||||
import { IRendererRuntime } from '../application/runtime/types';
|
||||
import { RendererRuntime } from '../application/runtime/types';
|
||||
import { BrowserModule, IClientApp } from '../browser-module';
|
||||
import { ClientAppContribution } from '../common';
|
||||
import { CorePreferences, injectCorePreferences } from '../core-preferences';
|
||||
|
@ -156,7 +157,7 @@ export class ClientApp implements IClientApp, IDisposable {
|
|||
this.injector.addProviders({ token: AppConfig, useValue: this.config });
|
||||
|
||||
this.runtime = isDesktop ? this.injector.get(ElectronRendererRuntime) : this.injector.get(BrowserRuntime);
|
||||
this.injector.addProviders({ token: IRendererRuntime, useValue: this.runtime });
|
||||
this.injector.addProviders({ token: RendererRuntime, useValue: this.runtime });
|
||||
|
||||
if (this.config.devtools) {
|
||||
// set a global so the opensumi devtools can identify that
|
||||
|
@ -586,7 +587,7 @@ export class ClientApp implements IClientApp, IDisposable {
|
|||
});
|
||||
injector.addProviders({
|
||||
token: StorageProvider,
|
||||
useFactory: () => (storageId) => injector.get(DefaultStorageProvider).get(storageId),
|
||||
useFactory: (injector) => (storageId: URI) => injector.get(DefaultStorageProvider).get(storageId),
|
||||
});
|
||||
createContributionProvider(injector, StorageResolverContribution);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ export abstract class BrowserModule<T = any> extends BasicModule {
|
|||
protected app: IClientApp;
|
||||
public preferences?: (inject: Injector) => void;
|
||||
public component?: React.ComponentType<T>;
|
||||
// 脱离于layout渲染的模块
|
||||
|
||||
// 脱离于文档流的模块
|
||||
public isOverlay?: boolean;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ export * from './design';
|
|||
// 前端工具方法
|
||||
export * from './logger';
|
||||
export * from './utils';
|
||||
export * from './worker';
|
||||
|
||||
export * from './context-key';
|
||||
|
||||
|
|
|
@ -223,7 +223,7 @@ export interface AppConfig {
|
|||
*/
|
||||
workspaceSuffixName?: string;
|
||||
/**
|
||||
* 视图组件内默认的组件样式资源 CDN 来源
|
||||
* 视图组件/内部使用的资源 CDN 来源
|
||||
* 默认值为 'alipay'
|
||||
*/
|
||||
componentCDNType?: TComponentCDNType;
|
||||
|
@ -305,3 +305,27 @@ export function ConfigProvider(props: React.PropsWithChildren<{ value: AppConfig
|
|||
}
|
||||
|
||||
export type TComponentCDNType = 'unpkg' | 'jsdelivr' | 'alipay' | 'npmmirror';
|
||||
|
||||
type IComponentCDNTypeMap = Record<TComponentCDNType, string>;
|
||||
|
||||
const CDN_TYPE_MAP: IComponentCDNTypeMap = {
|
||||
alipay: 'https://gw.alipayobjects.com/os/lib',
|
||||
npmmirror: 'https://registry.npmmirror.com',
|
||||
unpkg: 'https://unpkg.com/browse',
|
||||
jsdelivr: 'https://cdn.jsdelivr.net/npm',
|
||||
};
|
||||
|
||||
export function getCdnHref(
|
||||
packageName: string,
|
||||
filePath: string,
|
||||
version: string,
|
||||
cdnType: TComponentCDNType = 'alipay',
|
||||
) {
|
||||
if (cdnType === 'alipay') {
|
||||
return `${CDN_TYPE_MAP['alipay']}/${packageName.slice(1)}/${version}/${filePath}`;
|
||||
} else if (cdnType === 'npmmirror') {
|
||||
return `${CDN_TYPE_MAP['npmmirror']}/${packageName}/${version}/files/${filePath}`;
|
||||
} else {
|
||||
return `${CDN_TYPE_MAP[cdnType]}/${packageName}@${version}/${filePath}`;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,10 @@ export class StaticResourceServiceImpl implements StaticResourceService {
|
|||
};
|
||||
}
|
||||
|
||||
public removeStaticResourceProvider(scheme: string) {
|
||||
this.providers.delete(scheme);
|
||||
}
|
||||
|
||||
public resolveStaticResource(uri: URI): URI {
|
||||
if (!this.providers.has(uri.scheme)) {
|
||||
return uri;
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
export function getWorkerBootstrapUrl(scriptPath: string, label: string, ignoreCors?: boolean): string {
|
||||
if (ignoreCors) {
|
||||
return scriptPath;
|
||||
}
|
||||
|
||||
if (/^(http:)|(https:)|(file:)/.test(scriptPath)) {
|
||||
const currentUrl = String(window.location);
|
||||
const currentOrigin = currentUrl.substr(
|
||||
0,
|
||||
currentUrl.length - window.location.hash.length - window.location.search.length - window.location.pathname.length,
|
||||
);
|
||||
if (scriptPath.substring(0, currentOrigin.length) !== currentOrigin) {
|
||||
const js = `/*${label}*/importScripts('${scriptPath}');/*${label}*/`;
|
||||
const blob = new Blob([js], { type: 'application/javascript' });
|
||||
return URL.createObjectURL(blob);
|
||||
}
|
||||
}
|
||||
return scriptPath;
|
||||
}
|
|
@ -46,4 +46,14 @@ export namespace Schemes {
|
|||
export const userStorage = 'user_storage';
|
||||
|
||||
export const design = 'design';
|
||||
|
||||
/**
|
||||
* Scheme used for loading the WebAssembly files.
|
||||
*/
|
||||
export const wasm = 'wasm';
|
||||
|
||||
/**
|
||||
* Scheme used to loading the monaco utilities.
|
||||
*/
|
||||
export const monaco = 'monaco';
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ import {
|
|||
getDebugLogger,
|
||||
parseWithComments,
|
||||
} from '@opensumi/ide-core-browser';
|
||||
import { EKnownResources, IRendererRuntime } from '@opensumi/ide-core-browser/lib/application/runtime/types';
|
||||
import { EKnownResources, RendererRuntime } from '@opensumi/ide-core-browser/lib/application/runtime/types';
|
||||
import { Disposable, URI, isObject } from '@opensumi/ide-core-common';
|
||||
import { IFileServiceClient } from '@opensumi/ide-file-service/lib/common';
|
||||
import {
|
||||
|
@ -111,8 +111,8 @@ export class TextmateService extends WithEventBus implements ITextmateTokenizerS
|
|||
@Autowired(IEditorDocumentModelService)
|
||||
editorDocumentModelService: IEditorDocumentModelService;
|
||||
|
||||
@Autowired(IRendererRuntime)
|
||||
private rendererRuntime: IRendererRuntime;
|
||||
@Autowired(RendererRuntime)
|
||||
private rendererRuntime: RendererRuntime;
|
||||
|
||||
public grammarRegistry: Registry;
|
||||
|
||||
|
|
|
@ -1,19 +1 @@
|
|||
export function getWorkerBootstrapUrl(scriptPath: string, label: string, ignoreCors?: boolean): string {
|
||||
if (ignoreCors) {
|
||||
return scriptPath;
|
||||
}
|
||||
|
||||
if (/^(http:)|(https:)|(file:)/.test(scriptPath)) {
|
||||
const currentUrl = String(window.location);
|
||||
const currentOrigin = currentUrl.substr(
|
||||
0,
|
||||
currentUrl.length - window.location.hash.length - window.location.search.length - window.location.pathname.length,
|
||||
);
|
||||
if (scriptPath.substring(0, currentOrigin.length) !== currentOrigin) {
|
||||
const js = `/*${label}*/importScripts('${scriptPath}');/*${label}*/`;
|
||||
const blob = new Blob([js], { type: 'application/javascript' });
|
||||
return URL.createObjectURL(blob);
|
||||
}
|
||||
}
|
||||
return scriptPath;
|
||||
}
|
||||
export { getWorkerBootstrapUrl } from '@opensumi/ide-core-browser';
|
||||
|
|
|
@ -3,7 +3,13 @@ import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|||
import ReactDOM from 'react-dom';
|
||||
|
||||
import { ComponentContextProvider, IIconResourceOptions, IconContext } from '@opensumi/ide-components';
|
||||
import { DisposableCollection, LabelService, TComponentCDNType, useInjectable } from '@opensumi/ide-core-browser';
|
||||
import {
|
||||
DisposableCollection,
|
||||
LabelService,
|
||||
TComponentCDNType,
|
||||
getCdnHref as getCdnHrefRaw,
|
||||
useInjectable,
|
||||
} from '@opensumi/ide-core-browser';
|
||||
import { ExtensionBrowserStyleSheet, URI, localize } from '@opensumi/ide-core-common';
|
||||
import {
|
||||
IIconService,
|
||||
|
@ -25,15 +31,6 @@ function cloneNode<T>(head): T {
|
|||
return head.cloneNode(true);
|
||||
}
|
||||
|
||||
type IComponentCDNTypeMap = Record<TComponentCDNType, string>;
|
||||
|
||||
const CDN_TYPE_MAP: IComponentCDNTypeMap = {
|
||||
alipay: 'https://gw.alipayobjects.com/os/lib',
|
||||
npmmirror: 'https://registry.npmmirror.com',
|
||||
unpkg: 'https://unpkg.com/browse',
|
||||
jsdelivr: 'https://cdn.jsdelivr.net/npm',
|
||||
};
|
||||
|
||||
/**
|
||||
* 由于经过 clone 以后,实际 Shadow DOM 中 head 与原始 proxiedHead 不是同一份引用
|
||||
* 插件中可能存在后置动态插入 style 的行为,此时只会获取到 proxiedHead
|
||||
|
@ -76,13 +73,7 @@ function useMutationObserver(from: HTMLHeadElement, target: HTMLHeadElement) {
|
|||
const packageName = '@opensumi/ide-components';
|
||||
|
||||
function getCdnHref(filePath: string, version: string, cdnType: TComponentCDNType = 'alipay') {
|
||||
if (cdnType === 'alipay') {
|
||||
return `${CDN_TYPE_MAP['alipay']}/${packageName.slice(1)}/${version}/${filePath}`;
|
||||
} else if (cdnType === 'npmmirror') {
|
||||
return `${CDN_TYPE_MAP['npmmirror']}/${packageName}/${version}/files/${filePath}`;
|
||||
} else {
|
||||
return `${CDN_TYPE_MAP[cdnType]}/${packageName}@${version}/${filePath}`;
|
||||
}
|
||||
return getCdnHrefRaw(packageName, filePath, version, cdnType);
|
||||
}
|
||||
|
||||
function getStyleSheet(href: string) {
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
worker
|
|
@ -3,14 +3,17 @@
|
|||
"version": "3.0.2",
|
||||
"files": [
|
||||
"lib",
|
||||
"src"
|
||||
"src",
|
||||
"worker"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "lib/index.js",
|
||||
"typings": "lib/index.d.ts",
|
||||
"scripts": {
|
||||
"prepublishOnly": "yarn run build",
|
||||
"build": "tsc --build ../../configs/ts/references/tsconfig.monaco.json"
|
||||
"prepublishOnly": "yarn build",
|
||||
"build": "tsc --build ../../configs/ts/references/tsconfig.monaco.json && yarn build:worker",
|
||||
"build:worker": "../../node_modules/.bin/webpack --config webpack.config.js",
|
||||
"clean": "rimraf worker"
|
||||
},
|
||||
"dependencies": {
|
||||
"@opensumi/ide-core-browser": "workspace:*",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { Autowired, INJECTOR_TOKEN, Injector } from '@opensumi/di';
|
||||
import {
|
||||
AppConfig,
|
||||
ClientAppContribution,
|
||||
CommandContribution,
|
||||
ContributionProvider,
|
||||
|
@ -21,6 +22,10 @@ import {
|
|||
PreferenceScope,
|
||||
PreferenceService,
|
||||
ServiceNames,
|
||||
StaticResourceContribution,
|
||||
StaticResourceService,
|
||||
getCdnHref,
|
||||
getWorkerBootstrapUrl,
|
||||
} from '@opensumi/ide-core-browser';
|
||||
import {
|
||||
IMenuItem,
|
||||
|
@ -33,6 +38,7 @@ import {
|
|||
CommandService,
|
||||
DisposableCollection,
|
||||
ILogger,
|
||||
Schemes,
|
||||
URI,
|
||||
isOSX,
|
||||
isString,
|
||||
|
@ -90,9 +96,42 @@ import { KEY_CODE_MAP } from './monaco.keycode-map';
|
|||
import { MonacoResolvedKeybinding } from './monaco.resolved-keybinding';
|
||||
import { MonacoTelemetryService } from './telemetry.service';
|
||||
|
||||
@Domain(ClientAppContribution, CommandContribution, MenuContribution, KeybindingContribution)
|
||||
const pkgJson = require('../../package.json');
|
||||
|
||||
export interface Environment {
|
||||
/**
|
||||
* A web worker factory.
|
||||
* NOTE: If `getWorker` is defined, `getWorkerUrl` is not invoked.
|
||||
*/
|
||||
getWorker?(workerId: string, label: string): Promise<Worker> | Worker;
|
||||
/**
|
||||
* Return the location for web worker scripts.
|
||||
* NOTE: If `getWorker` is defined, `getWorkerUrl` is not invoked.
|
||||
*/
|
||||
getWorkerUrl?(workerId: string, label: string): string;
|
||||
}
|
||||
|
||||
interface Window {
|
||||
MonacoEnvironment?: Environment | undefined;
|
||||
}
|
||||
|
||||
const packageName = pkgJson.name;
|
||||
const packageVersion = pkgJson.version;
|
||||
|
||||
@Domain(
|
||||
ClientAppContribution,
|
||||
CommandContribution,
|
||||
MenuContribution,
|
||||
KeybindingContribution,
|
||||
StaticResourceContribution,
|
||||
)
|
||||
export class MonacoClientContribution
|
||||
implements ClientAppContribution, CommandContribution, MenuContribution, KeybindingContribution
|
||||
implements
|
||||
ClientAppContribution,
|
||||
CommandContribution,
|
||||
MenuContribution,
|
||||
KeybindingContribution,
|
||||
StaticResourceContribution
|
||||
{
|
||||
@Autowired(MonacoContribution)
|
||||
private readonly monacoContributionProvider: ContributionProvider<MonacoContribution>;
|
||||
|
@ -151,6 +190,12 @@ export class MonacoClientContribution
|
|||
@Autowired(KeybindingRegistry)
|
||||
private readonly keybindings: KeybindingRegistry;
|
||||
|
||||
@Autowired(StaticResourceService)
|
||||
private readonly staticResourceService: StaticResourceService;
|
||||
|
||||
@Autowired(AppConfig)
|
||||
private readonly appConfig: AppConfig;
|
||||
|
||||
get editorExtensionsRegistry(): typeof EditorExtensionsRegistry {
|
||||
return EditorExtensionsRegistry;
|
||||
}
|
||||
|
@ -215,6 +260,9 @@ export class MonacoClientContribution
|
|||
// 监听 preferences 更新事件,同步更新 mime
|
||||
this.setPreferencesChangeListener();
|
||||
|
||||
// 注册 monaco environment
|
||||
this.registerMonacoEnvironment();
|
||||
|
||||
// 修改一些 Monaco 内置 Services 的行为
|
||||
this.patchMonacoInternalServices();
|
||||
|
||||
|
@ -228,6 +276,28 @@ export class MonacoClientContribution
|
|||
this.keybindings.onKeybindingsChanged(() => this.updateMonacoKeybindings());
|
||||
}
|
||||
|
||||
registerMonacoEnvironment() {
|
||||
const defaultEnvironment = (window as Window).MonacoEnvironment || ({} as Environment);
|
||||
(window as Window).MonacoEnvironment = {
|
||||
getWorkerUrl: (moduleId, label) => {
|
||||
const result = this.staticResourceService.resolveStaticResource(
|
||||
URI.from({
|
||||
scheme: Schemes.monaco,
|
||||
path: 'worker',
|
||||
query: JSON.stringify({ moduleId, label }),
|
||||
}),
|
||||
);
|
||||
|
||||
if (result.scheme === Schemes.monaco) {
|
||||
throw new Error(`Unsupported monaco worker: ${moduleId}:${label}`);
|
||||
}
|
||||
|
||||
return getWorkerBootstrapUrl(result.toString(), `${moduleId}:${label}`);
|
||||
},
|
||||
...defaultEnvironment,
|
||||
};
|
||||
}
|
||||
|
||||
private registerOverrideServices() {
|
||||
const codeEditorService = this.overrideServicesRegistry.getRegisteredService<AbstractCodeEditorService>(
|
||||
ServiceNames.CODE_EDITOR_SERVICE,
|
||||
|
@ -531,6 +601,37 @@ export class MonacoClientContribution
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
registerStaticResolver(service: StaticResourceService): void {
|
||||
service.registerStaticResourceProvider({
|
||||
scheme: Schemes.monaco,
|
||||
resolveStaticResource: (uri) => {
|
||||
const path = uri.codeUri.path;
|
||||
|
||||
switch (path) {
|
||||
case 'worker': {
|
||||
const query = uri.query;
|
||||
if (query) {
|
||||
const { moduleId } = JSON.parse(query);
|
||||
if (moduleId === 'workerMain.js') {
|
||||
return URI.parse(
|
||||
getCdnHref(
|
||||
packageName,
|
||||
'worker/editor.worker.bundle.js',
|
||||
packageVersion,
|
||||
this.appConfig.componentCDNType,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return uri;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function transformMonacoMenuItem(item: monacoActions.IMenuItem | monacoActions.ISubmenuItem): IMenuItem | ISubmenuItem {
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
const path = require('path');
|
||||
|
||||
const TerserPlugin = require('terser-webpack-plugin');
|
||||
const webpack = require('webpack');
|
||||
const { WebpackManifestPlugin } = require('webpack-manifest-plugin');
|
||||
|
||||
/**
|
||||
* @type {import('webpack').Configuration}
|
||||
*/
|
||||
module.exports = {
|
||||
mode: process.env.NODE_ENV || 'development',
|
||||
entry: {
|
||||
'editor.worker': '@opensumi/monaco-editor-core/esm/vs/editor/editor.worker.js',
|
||||
},
|
||||
devtool: process.env.NODE_ENV === 'production' ? false : 'source-map',
|
||||
output: {
|
||||
globalObject: 'self',
|
||||
filename: '[name].bundle.js',
|
||||
path: path.resolve(__dirname, 'worker'),
|
||||
clean: true,
|
||||
publicPath: '',
|
||||
},
|
||||
optimization:
|
||||
process.env.NODE_ENV === 'production'
|
||||
? {
|
||||
minimize: true,
|
||||
minimizer: [new TerserPlugin()],
|
||||
}
|
||||
: {},
|
||||
plugins: [
|
||||
new WebpackManifestPlugin({}),
|
||||
new webpack.optimize.LimitChunkCountPlugin({
|
||||
maxChunks: 1,
|
||||
}),
|
||||
],
|
||||
stats: process.env.CI ? 'errors-only' : 'normal',
|
||||
};
|
25
yarn.lock
25
yarn.lock
|
@ -2020,6 +2020,7 @@ __metadata:
|
|||
tsx: "npm:^4.7.1"
|
||||
typescript: "npm:4.9.3"
|
||||
webpack: "npm:^5.90.0"
|
||||
webpack-manifest-plugin: "npm:^5.0.0"
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
|
@ -18010,7 +18011,7 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"source-list-map@npm:^2.0.0":
|
||||
"source-list-map@npm:^2.0.0, source-list-map@npm:^2.0.1":
|
||||
version: 2.0.1
|
||||
resolution: "source-list-map@npm:2.0.1"
|
||||
checksum: 10/3918ffba5fe8447bc816800026fe707aab233d9d05a3487225d880e23b7e37ed455b4e1b844e05644f6ecc7c9b837c0cc32da54dd37f77c993370ebcdb049246
|
||||
|
@ -19958,6 +19959,18 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"webpack-manifest-plugin@npm:^5.0.0":
|
||||
version: 5.0.0
|
||||
resolution: "webpack-manifest-plugin@npm:5.0.0"
|
||||
dependencies:
|
||||
tapable: "npm:^2.0.0"
|
||||
webpack-sources: "npm:^2.2.0"
|
||||
peerDependencies:
|
||||
webpack: ^5.47.0
|
||||
checksum: 10/466ade444c23d4a8ec3d1a108ec2142468cb260570533acf2cf68806065ccdef649dbac0fa6b0700f4c6d2497535ae950a20e83b26edb25ccfa9bb51538fa607
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"webpack-merge@npm:^5.10.0, webpack-merge@npm:^5.7.3":
|
||||
version: 5.10.0
|
||||
resolution: "webpack-merge@npm:5.10.0"
|
||||
|
@ -19979,6 +19992,16 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"webpack-sources@npm:^2.2.0":
|
||||
version: 2.3.1
|
||||
resolution: "webpack-sources@npm:2.3.1"
|
||||
dependencies:
|
||||
source-list-map: "npm:^2.0.1"
|
||||
source-map: "npm:^0.6.1"
|
||||
checksum: 10/0c4bb91f2899205648da25b68edf4495a360692af2c426cde98b188367478c93d5e33e2b08665e070ac0ece59ade8d52175da656a212b44701ce4a271ca66695
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"webpack-sources@npm:^3.2.3":
|
||||
version: 3.2.3
|
||||
resolution: "webpack-sources@npm:3.2.3"
|
||||
|
|
Loading…
Reference in New Issue