feat: eo-monaco-editor component

This commit is contained in:
renqian805 2022-07-29 09:24:44 +08:00
parent 5404929c4e
commit c54f470c7d
11 changed files with 10313 additions and 10772 deletions

View File

@ -1,224 +1 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"cli": {
"analytics": false,
"defaultCollection": "@angular-eslint/schematics"
},
"version": 1,
"newProjectRoot": "projects",
"projects": {
"eoapi": {
"root": "",
"i18n": {
"sourceLocale": {
"code": "en"
},
"locales": {
"zh": {
"translation": "src/locale/messages.zh.xlf"
}
}
},
"sourceRoot": "src",
"projectType": "application",
"schematics": {
"@schematics/angular:application": {
"strict": true
}
},
"architect": {
"build": {
"builder": "@angular-builders/custom-webpack:browser",
"options": {
"localize": true,
"aot": true,
"outputPath": "dist",
"index": "src/index.html",
"main": "src/main.ts",
"tsConfig": "src/tsconfig.app.json",
"polyfills": "src/polyfills.ts",
"assets": [
"src/icon.ico",
"src/assets",
{
"glob": "**/*",
"input": "../../../node_modules/@ant-design/icons-angular/src/inline-svg/",
"output": "/assets/"
},
{
"glob": "**/*",
"input": "../../../node_modules/monaco-editor/min/vs",
"output": "/assets/vs/"
}
],
"styles": [
{
"input": "src/assets/theme/classic_forest.scss",
"bundleName": "classic_forest",
"inject": false
},
"src/styles.scss",
"src/assets/theme/antd.less",
"src/assets/font/iconfont.css",
"src/ng1/index.css"
],
"scripts": [
"src/ng1/lib/angular/angular.js",
"src/ng1/app.module.js",
"src/ng1/component/select-default.js",
"src/ng1/component/sort-and-filter.js",
"src/ng1/component/auto-complete.js",
"src/ng1/component/list-block.js",
"src/ng1/directive/get-dom-length.directive.js",
"src/ng1/directive/drop-down-menu.directive.js",
"src/ng1/directive/sort.directive.js",
"src/ng1/directive/drop-change-space.directive.js",
"src/ng1/directive/inner-html.directive.js",
"src/ng1/directive/insert-html.directive.js",
"src/ng1/directive/copy-common.directive.js"
],
"customWebpackConfig": {
"path": "./angular.webpack.js",
"replaceDuplicatePlugins": true
},
"allowedCommonJsDependencies": ["brace", "qs", "rxjs"]
},
"configurations": {
"dev": {
"optimization": false,
"outputHashing": "none",
"sourceMap": true,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": false,
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.dev.ts"
}
]
},
"web": {
"optimization": false,
"outputHashing": "none",
"sourceMap": true,
"namedChunks": false,
"localize": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": false,
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.web.ts"
}
]
},
"webCn": {
"optimization": false,
"outputHashing": "none",
"sourceMap": true,
"namedChunks": false,
"localize": ["zh"],
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": false,
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.web.ts"
}
]
},
"production": {
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
]
}
}
},
"serve": {
"builder": "@angular-builders/custom-webpack:dev-server",
"options": {
"browserTarget": "eoapi:build"
},
"configurations": {
"dev": {
"browserTarget": "eoapi:build:dev"
},
"web": {
"browserTarget": "eoapi:build:web"
},
"webCn": {
"browserTarget": "eoapi:build:webCn"
},
"production": {
"browserTarget": "eoapi:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "eoapi:build"
}
},
"test": {
"builder": "@angular-builders/custom-webpack:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills-test.ts",
"tsConfig": "src/tsconfig.spec.json",
"karmaConfig": "src/karma.conf.js",
"scripts": [],
"styles": ["src/styles.scss"],
"assets": ["src/assets"],
"customWebpackConfig": {
"path": "./angular.webpack.js",
"replaceDuplicatePlugins": true
}
}
},
"lint": {
"builder": "@angular-eslint/builder:lint",
"options": {
"lintFilePatterns": ["src/**/*.ts", "src/**/*.html"]
}
}
}
},
"eoapi-e2e": {
"root": "e2e",
"projectType": "application",
"architect": {
"lint": {
"builder": "@angular-eslint/builder:lint",
"options": {
"lintFilePatterns": ["e2e/**/*.ts"]
}
}
}
}
},
"defaultProject": "eoapi",
"schematics": {
"@schematics/angular:component": {
"prefix": "eo",
"style": "scss"
},
"@schematics/angular:directive": {
"prefix": "eo"
}
}
}
{"$schema":"./node_modules/@angular/cli/lib/config/schema.json","cli":{"analytics":false,"defaultCollection":"@angular-eslint/schematics"},"version":1,"newProjectRoot":"projects","projects":{"eoapi":{"root":"","i18n":{"sourceLocale":{"code":"en","baseHref":""},"locales":{"zh":{"translation":"src/locale/messages.zh.xlf","baseHref":""}}},"sourceRoot":"src","projectType":"application","schematics":{"@schematics/angular:application":{"strict":true}},"architect":{"build":{"builder":"@angular-builders/custom-webpack:browser","options":{"localize":true,"aot":true,"outputPath":"dist","index":"src/index.html","main":"src/main.ts","tsConfig":"src/tsconfig.app.json","polyfills":"src/polyfills.ts","assets":["src/icon.ico","src/assets",{"glob":"**/*","input":"../../../node_modules/@ant-design/icons-angular/src/inline-svg/","output":"/assets/"},{"glob":"**/*","input":"../../../node_modules/monaco-editor/min/vs","output":"/assets/vs/"}],"styles":[{"input":"src/assets/theme/classic_forest.scss","bundleName":"classic_forest","inject":false},"src/styles.scss","src/assets/theme/antd.less","src/assets/font/iconfont.css","src/ng1/index.css"],"scripts":["src/ng1/lib/angular/angular.js","src/ng1/app.module.js","src/ng1/component/select-default.js","src/ng1/component/sort-and-filter.js","src/ng1/component/auto-complete.js","src/ng1/component/list-block.js","src/ng1/directive/get-dom-length.directive.js","src/ng1/directive/drop-down-menu.directive.js","src/ng1/directive/sort.directive.js","src/ng1/directive/drop-change-space.directive.js","src/ng1/directive/inner-html.directive.js","src/ng1/directive/insert-html.directive.js","src/ng1/directive/copy-common.directive.js"],"customWebpackConfig":{"path":"./angular.webpack.js","replaceDuplicatePlugins":true},"allowedCommonJsDependencies":["brace","qs","rxjs"]},"configurations":{"dev":{"optimization":false,"outputHashing":"none","sourceMap":true,"namedChunks":false,"extractLicenses":true,"vendorChunk":false,"buildOptimizer":false,"fileReplacements":[{"replace":"src/environments/environment.ts","with":"src/environments/environment.dev.ts"}]},"web":{"optimization":false,"outputHashing":"none","sourceMap":true,"namedChunks":false,"localize":false,"extractLicenses":true,"vendorChunk":false,"buildOptimizer":false,"fileReplacements":[{"replace":"src/environments/environment.ts","with":"src/environments/environment.web.ts"}]},"webCn":{"optimization":false,"outputHashing":"none","sourceMap":true,"namedChunks":false,"localize":["zh"],"extractLicenses":true,"vendorChunk":false,"buildOptimizer":false,"fileReplacements":[{"replace":"src/environments/environment.ts","with":"src/environments/environment.web.ts"}]},"production":{"optimization":true,"outputHashing":"all","sourceMap":false,"namedChunks":false,"extractLicenses":true,"vendorChunk":false,"buildOptimizer":true,"fileReplacements":[{"replace":"src/environments/environment.ts","with":"src/environments/environment.prod.ts"}]}}},"serve":{"builder":"@angular-builders/custom-webpack:dev-server","options":{"browserTarget":"eoapi:build"},"configurations":{"dev":{"browserTarget":"eoapi:build:dev"},"web":{"browserTarget":"eoapi:build:web"},"webCn":{"browserTarget":"eoapi:build:webCn"},"production":{"browserTarget":"eoapi:build:production"}}},"extract-i18n":{"builder":"@angular-devkit/build-angular:extract-i18n","options":{"browserTarget":"eoapi:build"}},"test":{"builder":"@angular-builders/custom-webpack:karma","options":{"main":"src/test.ts","polyfills":"src/polyfills-test.ts","tsConfig":"src/tsconfig.spec.json","karmaConfig":"src/karma.conf.js","scripts":[],"styles":["src/styles.scss"],"assets":["src/assets"],"customWebpackConfig":{"path":"./angular.webpack.js","replaceDuplicatePlugins":true}}},"lint":{"builder":"@angular-eslint/builder:lint","options":{"lintFilePatterns":["src/**/*.ts","src/**/*.html"]}}}},"eoapi-e2e":{"root":"e2e","projectType":"application","architect":{"lint":{"builder":"@angular-eslint/builder:lint","options":{"lintFilePatterns":["e2e/**/*.ts"]}}}}},"defaultProject":"eoapi","schematics":{"@schematics/angular:component":{"prefix":"eo","style":"scss"},"@schematics/angular:directive":{"prefix":"eo"}}}

View File

@ -1,6 +1,5 @@
//Polyfill Node.js core modules in Webpack. This module is only needed for webpack 5+.
const NodePolyfillPlugin = require('node-polyfill-webpack-plugin');
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
/**
* Custom angular webpack configuration
@ -26,7 +25,6 @@ module.exports = (config, options) => {
new NodePolyfillPlugin({
excludeAliases: ['console'],
}),
new MonacoWebpackPlugin(),
];
return config;

View File

@ -77,7 +77,6 @@
"karma-coverage-istanbul-reporter": "3.0.3",
"karma-jasmine": "5.1.0",
"karma-jasmine-html-reporter": "2.0.0",
"monaco-editor-webpack-plugin": "7.0.1",
"node-polyfill-webpack-plugin": "2.0.0",
"postcss": "8.4.14",
"tailwindcss": "3.1.4",

View File

@ -4,7 +4,6 @@ import { NgModule, CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA, LOCALE_ID } from '@
import { EouiModule } from 'eo/workbench/browser/src/app/eoui/eoui.module';
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';
import { NzConfig, NZ_CONFIG } from 'ng-zorro-antd/core/config';
//Other module
import { CoreModule } from './core/core.module';
@ -37,12 +36,6 @@ import { ExtensionService } from 'eo/workbench/browser/src/app/pages/extension/e
registerLocaleData(en);
registerLocaleData(zh);
const ngZorroConfig: NzConfig = {
codeEditor: {
useStaticLoading: true,
},
};
@NgModule({
declarations: [AppComponent],
imports: [

View File

@ -24,8 +24,9 @@
<!-- Raw -->
<!-- <eo-editor [(code)]="model" *ngIf="bodyType === 'raw'" (codeChange)="rawDataChange()" [config]="{ maxLines: 10 }"
[eventList]="['type', 'format', 'copy', 'search', 'replace']"></eo-editor> -->
<nz-code-editor *ngIf="bodyType === 'raw'" class="editor" [ngModel]="code" style="height: 300px;"
[nzEditorOption]="{ language: 'typescript' }"></nz-code-editor>
<eo-monaco-editor *ngIf="bodyType === 'raw'" [(code)]="model"
[eventList]="['type', 'format', 'copy', 'search', 'replace']" (codeChange)="rawDataChange()">
</eo-monaco-editor>
<!-- Binary -->
<textarea class="binary_textarea" rows="4" *ngIf="bodyType === 'binary'" nzBorderless i18n-placeholder
(ngModelChange)="rawDataChange()" placeholder="Binary Description" nz-input [(ngModel)]="model"></textarea>

View File

@ -16,7 +16,10 @@ import { ApiEditService } from '../api-edit.service';
styleUrls: ['./api-edit-body.component.scss'],
})
export class ApiEditBodyComponent implements OnInit, OnChanges, OnDestroy {
@Input() model: string | object[] | any;
@Input() model: string | object[] | any = `import { NzCodeEditorModule } from 'ng-zorro-antd/code-editor'
@Component({})
export class SomeComponent {}`;
@Input() supportType: string[];
@Input() bodyType: ApiBodyType | string;
@Input() jsonRootType: JsonRootType | string;
@ -25,10 +28,7 @@ export class ApiEditBodyComponent implements OnInit, OnChanges, OnDestroy {
@Output() modelChange: EventEmitter<any> = new EventEmitter();
listConf: any = {};
cache: any = {};
code = `import { NzCodeEditorModule } from 'ng-zorro-antd/code-editor'
@Component({})
export class SomeComponent {}`;
CONST: any = {
JSON_ROOT_TYPE: Object.keys(JsonRootType).map((val) => ({ key: val, value: JsonRootType[val] })),
};

View File

@ -0,0 +1,8 @@
<div class="button_list">
<div class="flex btn" (click)="handleAction(item.event)" *ngFor="let item of buttonList">
<eo-iconpark-icon class="mr5" name="{{item.icon}}" size="14px"></eo-iconpark-icon>
<span>{{ item.label }}</span>
</div>
</div>
<nz-code-editor [ngModel]="code" style="height: 300px;" [nzEditorOption]="{ language: 'typescript' }"
(nzEditorInitialized)="onEditorInitialized($event)"></nz-code-editor>

View File

@ -0,0 +1,50 @@
.eo-editor {
min-height: var(--eo-editor-height, 70px);
}
.button_list {
border: 1px solid var(--BORDER);
border-top-left-radius: 3px;
border-top-right-radius: 3px;
width: 100%;
display: flex;
font-size: 12px;
align-items: center;
padding-left: 10px;
nz-select {
width: 90px;
}
.btn {
display: inline-flex;
align-items: center;
height: 30px;
padding: 10px;
cursor: pointer;
background-color: var(--MAIN_BG);
color: var(--MAIN_TEXT);
&:hover {
color: var(--BLUE_NORMAL);
}
> i {
margin: 0 5px;
}
}
}
::ng-deep eo-editor {
height: 100%;
& > div {
height: 100%;
}
.ace_editor {
min-height: inherit !important;
}
.ace-editor {
height: calc(100% - 52px);
min-height: inherit;
overflow: auto;
&::-webkit-scrollbar {
width: 0;
}
}
}

View File

@ -0,0 +1,180 @@
import { Component, Input, Output, EventEmitter, OnChanges, AfterViewInit, ViewChild, OnInit } from '@angular/core';
import { EoMessageService } from 'eo/workbench/browser/src/app/eoui/message/eo-message.service';
import { whatTextType } from '../../../utils';
import { ElectronService } from 'eo/workbench/browser/src/app/core/services/electron/electron.service';
import { editor } from 'monaco-editor';
type EventType = 'format' | 'copy' | 'search' | 'replace' | 'type' | 'download' | 'newTab';
const eventHash = new Map()
.set('format', {
label: $localize`Format`,
icon: 'magic',
})
.set('copy', {
label: $localize`:@@Copy:Copy`,
icon: 'copy',
})
.set('search', {
label: $localize`:@@Search:Search`,
icon: 'search',
})
.set('replace', {
label: $localize`Replace`,
icon: 'file-text-one',
});
@Component({
selector: 'eo-monaco-editor',
templateUrl: './monaco-editor.component.html',
styleUrls: ['./monaco-editor.component.scss'],
})
export class EoMonacoEditorComponent implements AfterViewInit, OnInit, OnChanges {
@Input() eventList: EventType[] = [];
@Input() hiddenList: string[] = [];
@Input() code: string;
@Input() minHeight = '70';
@Input() editorType = 'json';
@Input() autoFormat = false;
@Input() disabled = false;
@Input() completions = [];
@Output() codeChange = new EventEmitter<string>();
codeEdtor: editor.IStandaloneCodeEditor;
isReadOnly = false;
buttonList: any[] = [];
typeList = [
{
value: 'json',
label: 'JSON',
},
{
value: 'xml',
label: 'XML',
},
{
value: 'html',
label: 'HTML',
},
{
value: 'text',
label: 'Text',
},
];
isNaN(val) {
return Number.isNaN(Number(val));
}
constructor(private message: EoMessageService, private electron: ElectronService) {}
ngAfterViewInit(): void {
console.log('codeEdtor', this.codeEdtor);
}
ngOnChanges() {
// * update root type
if (this.eventList.includes('type') && !this.hiddenList.includes('type')) {
const type = whatTextType(this.code || '');
this.editorType = type;
if (this.autoFormat) {
this.code = this.formatCode(this.code, type);
}
}
}
ngOnInit() {
// console.log(this.eventList);
// To get the Ace instance:
this.buttonList = this.electron.isElectron
? this.eventList
.filter((it) => !['newTab', 'type'].includes(it))
.map((it) => ({
event: it,
...eventHash.get(it),
}))
: this.eventList
.filter((it) => it !== 'type')
.map((it) => ({
event: it,
...eventHash.get(it),
}));
}
log(event, txt) {
console.log('ace event', event, txt);
}
handleBlur() {
setTimeout(() => {
this.codeChange.emit(this.code);
}, 0);
}
handleChange() {
setTimeout(() => {
this.codeChange.emit(this.code);
}, 0);
}
rerenderAce() {}
formatCode(code, type) {
return code;
}
handleAction(event) {
const ace = {} as any;
const session = ace.getSession();
switch (event) {
case 'format': {
// * format code
const value = session.getValue();
const code = this.formatCode(value, this.editorType);
session.setValue(code);
break;
}
case 'copy': {
// * copy content
const value = session.getValue();
if (navigator.clipboard) {
navigator.clipboard.writeText(value);
this.message.success($localize`Copied`);
return;
}
break;
}
case 'search': {
// * search content
ace.execCommand('find');
break;
}
case 'replace': {
ace.execCommand('replace');
break;
}
case 'newTab':
{
const tmpNewWin = window.open();
const value = session.getValue();
const code = this.formatCode(value, this.editorType);
tmpNewWin.document.open();
tmpNewWin.document.write(code);
tmpNewWin.document.close();
}
break;
case 'download':
{
const value = session.getValue();
const code = this.formatCode(value, this.editorType);
const a = document.createElement('a');
const blob = new Blob([code]);
const url = window.URL.createObjectURL(blob);
const filename = `download.${this.editorType}`;
a.href = url;
a.download = filename;
a.click();
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
}
break;
}
}
handleInsert(code) {}
onEditorInitialized(codeEdtor) {
this.codeEdtor = codeEdtor;
}
}

View File

@ -30,6 +30,7 @@ import { EouiModule } from 'eo/workbench/browser/src/app/eoui/eoui.module';
import { NzTreeModule } from 'ng-zorro-antd/tree';
import { EnvListComponent } from 'eo/workbench/browser/src/app/shared/components/env-list/env-list.component';
import { SplitPanelComponent } from 'eo/workbench/browser/src/app/shared/components/split-panel/split.panel.component';
import { EoMonacoEditorComponent } from 'eo/workbench/browser/src/app/shared/components/monaco-editor/monaco-editor.component';
import { NzEmptyModule } from 'ng-zorro-antd/empty';
const COMPONENTS = [
@ -39,6 +40,7 @@ const COMPONENTS = [
PageNotFoundComponent,
ApiScriptComponent,
SplitPanelComponent,
EoMonacoEditorComponent,
];
@NgModule({
imports: [
@ -76,6 +78,7 @@ const COMPONENTS = [
EoIconparkIconModule,
EnvListComponent,
SplitPanelComponent,
EoMonacoEditorComponent,
],
})
export class SharedModule {}

20596
yarn.lock

File diff suppressed because it is too large Load Diff