Skip to content

Commit

Permalink
feat(module:monaco-editor): support static loading (#4341)
Browse files Browse the repository at this point in the history
* feat(module:code-editor): support static loading

* feat(module:code-editor): use global config service

* docs: monaco editor

* fix: fix style import path

* fix: fix style import
  • Loading branch information
Wendell authored and hsuanxyz committed Nov 7, 2019
1 parent dcc7deb commit 29f732b
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 23 deletions.
16 changes: 14 additions & 2 deletions components/code-editor/doc/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Support monaco editor in Angular.

## API

Before using this component, you should load resources of monaco editor itself. You can load these resources with Angular CLI. Write this configuration in angular.json:
If you would like to load monaco dynamically, you will need assets of monaco editor itself. You can do that load by adding these lines in angular.json:

```diff
"assets": [
Expand All @@ -26,7 +26,7 @@ Before using this component, you should load resources of monaco editor itself.
],
```

Or you can provide an `assetsRoot` to determine where should the component load resources of monaco editor.
> If you are going to use static loading (which we will explain in detail at the bottom of this page), you don't need to modify angular.json file.
And don't forget to install `monaco-editor`.

Expand Down Expand Up @@ -63,4 +63,16 @@ You can inject an object that implements `NzCodeEditorConfig` with the injection
| `onLoad` | The hook invoked when the resource of monaco editor is loaded. At this moment and afterwards the global variable `monaco` is usable | `() => void` | - |
| `onFirstEditorInit` | The hook invoked when the first monaco editor is initialized | `() => void` | - |
| `onInit` | The hook invoked every time a monaco editor is initialized | `() => void` | - |
| `useStaticLoading` | Load monaco editor statically | `boolean` | `false` |

## Static Loading

Sometimes you need to load AMD module dynamically. But since monaco editor's loader patches `window[require]`, you can not use AMD loader like requireJS. In this situation you need to enable static loading.

With help of [monaco-editor-webpack-plguin](https://github.com/microsoft/monaco-editor-webpack-plugin) by Microsoft, you can do that in a convenient way.

1. Please inject a `NZ_CODE_EDITOR_CONFIG` with `useStaticLoading` to be `true`.
2. Create a webpack.partial.js file, and config monaco-editor-webpack-loader.
3. Use custom webpack loader like [ngx-build-plus](https://github.com/manfredsteyer/ngx-build-plus) to load this webpack config.

If you use static loading, you should not add assets of monaco editor to your project by modifying angular.json file.
17 changes: 15 additions & 2 deletions components/code-editor/doc/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ monaco editor 组件。

## API

使用该组件之前,需要加载 monaco editor 本身的资源。你可以通过 Angular CLI 提供的配置项将这些资源添加到 assets 目录下。例子,`angular.json` 中添加:
如果你使用动态加载的引入方式,你就需要在运行时加载 monaco editor 本身的资源。在 `angular.json` 中添加:

```diff
"assets": [
Expand All @@ -27,7 +27,7 @@ monaco editor 组件。
],
```

或者通过修改配置项中的 `assetsRoot` 指定资源位置
> 如果你使用静态加载,你就无需修改 angular.json 文件。详见下文
另外别忘记安装 monaco editor:

Expand Down Expand Up @@ -64,3 +64,16 @@ npm install monaco-editor
| `onLoad` | 当 monaco editor 资源加载完毕时触发的钩子,此时全局对象 `monaco` 可用 | `() => void` | - |
| `onFirstEditorInit` | 当第一个编辑器请求初始化时触发的钩子 | `() => void` | - |
| `onInit` | 每个编辑器请求初始化时触发的钩子 | `() => void` | - |
| `useStaticLoading` | 使用静态加载 | `boolean` | `false` |

## 静态加载

有时候你可能需要动态加载 AMD module,但 monaco editor 的加载文件 loader.js patch 了 `window[require]` 对象,导致你无法使用 requireJS 等模块加载库,这时,你可以启用静态加载功能。

方法是使用 Microsoft 提供的 [monaco-editor-webpack-plugin](https://github.com/microsoft/monaco-editor-webpack-plugin) 插件。

1. 在注入 code editor 组件的全局配置项时,请启用 `useStaticLoading`
2. 创建一个 webpack.partial.js 文件,根据插件文档进行相应的配置
3. 使用自定义脚本加载器,例如 [ngx-build-plus](https://github.com/manfredsteyer/ngx-build-plus),在打包时加载这个 webpack 配置

使用静态加载时,你无需在 angular.json 文件中注册 monaco editor 的资源。
2 changes: 2 additions & 0 deletions components/code-editor/nz-code-editor.definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ export enum NzCodeEditorLoadingStatus {
export interface NzCodeEditorConfig {
assetsRoot?: string | SafeUrl;
defaultEditorOption?: JoinedEditorOptions;
useStaticLoading?: boolean;

onLoad?(): void;
onFirstEditorInit?(): void;
onInit?(): void;
Expand Down
68 changes: 54 additions & 14 deletions components/code-editor/nz-code-editor.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
*/

import { DOCUMENT } from '@angular/common';
import { Inject, Injectable } from '@angular/core';
import { Inject, Injectable, Optional } from '@angular/core';
import { of as observableOf, BehaviorSubject, Observable, Subject } from 'rxjs';
import { map, tap } from 'rxjs/operators';

import { PREFIX } from 'ng-zorro-antd/core';
import { warn, warnDeprecation, NzConfigService, PREFIX } from 'ng-zorro-antd/core';
import {
JoinedEditorOptions,
NzCodeEditorConfig,
Expand All @@ -22,6 +22,8 @@ import {
// tslint:disable-next-line no-any
declare const monaco: any;

const NZ_CONFIG_COMPONENT_NAME = 'codeEditor';

// tslint:disable no-any
function tryTriggerFunc(fn?: (...args: any[]) => any): (...args: any) => void {
return (...args: any[]) => {
Expand All @@ -41,19 +43,43 @@ export class NzCodeEditorService {
private loaded$ = new Subject<boolean>();
private loadingStatus = NzCodeEditorLoadingStatus.UNLOAD;
private option: JoinedEditorOptions;
private config: NzCodeEditorConfig;

option$ = new BehaviorSubject<JoinedEditorOptions>(this.option);

constructor(
@Inject(NZ_CODE_EDITOR_CONFIG) private config: NzCodeEditorConfig,
@Inject(DOCUMENT) _document: any // tslint:disable-line no-any
private readonly nzConfigService: NzConfigService,
@Inject(DOCUMENT) _document: any, // tslint:disable-line no-any
@Inject(NZ_CODE_EDITOR_CONFIG) @Optional() config?: NzCodeEditorConfig
) {
const globalConfig = this.nzConfigService.getConfigForComponent(NZ_CONFIG_COMPONENT_NAME);

if (config) {
warnDeprecation(
`'NZ_CODE_EDITOR_CONFIG' is deprecated and will be removed in next minor version. Please use 'NzConfigService' instead.`
);
}

this.document = _document;
this.option = this.config.defaultEditorOption || {};
this.option = { ...(this.config || {}).defaultEditorOption, ...(globalConfig || {}).defaultEditorOption };

this.nzConfigService.getConfigChangeEventForComponent(NZ_CONFIG_COMPONENT_NAME).subscribe(() => {
const newGlobalConfig = this.nzConfigService.getConfigForComponent(NZ_CONFIG_COMPONENT_NAME);
if (newGlobalConfig) {
this._updateDefaultOption(newGlobalConfig.defaultEditorOption);
}
});
}

// TODO: use config service later.
updateDefaultOption(option: JoinedEditorOptions): void {
warnDeprecation(
`'updateDefaultOption' is deprecated and will be removed in next minor version. Please use 'set' of 'NzConfigService' instead.`
);

this._updateDefaultOption(option);
}

private _updateDefaultOption(option: JoinedEditorOptions): void {
this.option = { ...this.option, ...option };
this.option$.next(this.option);

Expand All @@ -69,7 +95,15 @@ export class NzCodeEditorService {
}

if (this.loadingStatus === NzCodeEditorLoadingStatus.UNLOAD) {
this.loadMonacoScript();
if (this.config.useStaticLoading && typeof monaco === 'undefined') {
warn(
'You choose to use static loading but it seems that you forget ' +
'to config webpack plugin correctly. Please refer to our official website' +
'for more details about static loading.'
);
} else {
this.loadMonacoScript();
}
}

return this.loaded$.asObservable().pipe(
Expand All @@ -79,6 +113,11 @@ export class NzCodeEditorService {
}

private loadMonacoScript(): void {
if (this.config.useStaticLoading) {
this.onLoad();
return;
}

if (this.loadingStatus === NzCodeEditorLoadingStatus.LOADING) {
return;
}
Expand All @@ -97,9 +136,6 @@ export class NzCodeEditorService {
paths: { vs }
});
windowAsAny.require(['vs/editor/editor.main'], () => {
this.loadingStatus = NzCodeEditorLoadingStatus.LOADED;
this.loaded$.next(true);
this.loaded$.complete();
this.onLoad();
});
};
Expand All @@ -110,6 +146,14 @@ export class NzCodeEditorService {
this.document.documentElement.appendChild(loadScript);
}

private onLoad(): void {
this.loadingStatus = NzCodeEditorLoadingStatus.LOADED;
this.loaded$.next(true);
this.loaded$.complete();

tryTriggerFunc(this.config.onLoad)();
}

private onInit(): void {
if (!this.firstEditorInitialized) {
this.firstEditorInitialized = true;
Expand All @@ -119,10 +163,6 @@ export class NzCodeEditorService {
tryTriggerFunc(this.config.onInit)();
}

private onLoad(): void {
tryTriggerFunc(this.config.onLoad)();
}

private getLatestOption(): JoinedEditorOptions {
return { ...this.option };
}
Expand Down
2 changes: 2 additions & 0 deletions components/code-editor/style/entry.less
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
@import "./index.less";
// style dependencies
@import "../../spin/style/index.less";
14 changes: 12 additions & 2 deletions components/core/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@ import { InjectionToken, TemplateRef, Type } from '@angular/core';

import { NzAlignType, NzShapeSCType, NzSizeDSType, NzSizeLDSType, NzSizeMDSType } from '../types';

import { SafeUrl } from '@angular/platform-browser';
import { BreakpointMap, NzBreakpoint } from '../responsive/public-api';

// TODO: generate config files if custom build can be used.

export interface NzConfig {
affix?: AffixConfig;
alert?: AlertConfig;
Expand All @@ -25,6 +24,7 @@ export interface NzConfig {
card?: CardConfig;
carousel?: CarouselConfig;
cascader?: CascaderConfig;
codeEditor?: CodeEditorConfig;
collapse?: CollapseConfig;
collapsePanel?: CollapsePanelConfig;
descriptions?: DescriptionsConfig;
Expand Down Expand Up @@ -84,6 +84,16 @@ export interface ButtonConfig {
nzSize?: 'large' | 'default' | 'small';
}

export interface CodeEditorConfig {
assetsRoot?: string | SafeUrl;
defaultEditorOption?: any; // tslint:disable-line no-any
useStaticLoading?: boolean;

onLoad?(): void;
onFirstEditorInit?(): void;
onInit?(): void;
}

export interface CardConfig {
nzSize?: NzSizeDSType;
nzHoverable?: boolean;
Expand Down
2 changes: 1 addition & 1 deletion docs/global-config.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ order: 7
title: Global Configuration
---

From version 8.3.0, we add support of **global configuration** to many components. You can define the default behavior of the component through global configuration, thus reducing the code that needs to be written in the template, and implement feature that is similar to switching themes.
From version 8.3.0, we add support of **global configuration** to many components. You can define the default behavior of the component through global configuration, thus reducing the code that needs to be written in the template, and support changing global config at runtime.

<blockquote style="border-color: red;"><p><strong>The injection tokens provided by components previously will be removed in the 9.x versions. Please migrate to the new API <code>NZ_CONFIG</code>.</strong></p></blockquote>

Expand Down
4 changes: 2 additions & 2 deletions docs/global-config.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ order: 7
title: 全局配置项
---

从 8.3.0 版本开始,我们给众多组件添加了**全局配置**功能,你可以通过全局配置来定义组件的默认行为,从而减少在模板中需要写的代码(让你的代码更加清爽),还能实现类似于切换主题的功能
从 8.3.0 版本开始,我们给众多组件添加了**全局配置**功能,你可以通过全局配置来定义组件的默认行为,从而减少在模板中需要写的代码(让你的代码更加清爽),还能在运行时修改全局配置项

<blockquote style="border-color: red;"><p><strong>之前各组件单独提供的注入令牌将会在 ng-zorro-antd 9.x 版本中移除,请及时迁移!</strong></p></blockquote>

Expand All @@ -15,7 +15,7 @@ title: 全局配置项
import { NgZorroAntdModule, NzConfig, NZ_CONFIG } from 'ng-zorro-antd';

const ngZorroConfig: NzConfig = {
// 注意没有 nz 前缀
// 注意组件名称没有 nz 前缀
message: { nzTop: 120 },
notification: { nzTop: 240 }
};
Expand Down

0 comments on commit 29f732b

Please sign in to comment.