天天看點

使用微軟Monaco Editor 編寫代碼比對工具前言環境及元件實作

前言

微軟之前有個項目叫做Monaco Workbench,後來這個項目變成了VS Code,而Monaco Editor就是從這個項目中成長出來的一個web編輯器,是以Monaco Editor和VS Code在編輯代碼,互動以及UI上幾乎是一摸一樣的,有點不同的是,兩者的平台不一樣,Monaco Editor基于浏覽器,而VS Code基于electron,是以功能上VSCode更加健全,并且性能比較強大。本文主要介紹ng-zorro 架構內建Monaco Editor實作文本比對。Monaco Editor 不僅能做文本比對,同樣可以做代碼編輯器,可以查閱《使用微軟Monaco Editor 編寫線上調試工具》。

環境及元件

Monaco Editor 微軟 Monaco Editor 編輯器

Ant Design of Angular NG-ZORRO

ngx-monaco-editor monaco-editor angular npm 包

實作

根據 ngx-monaco-editor 文檔按angular版本安裝指定版本的npm包

注意:版本對應不上會導緻資源404錯誤

  • Angular <= 4: v3.x.x
  • Angular 5: v5.x.x
  • Angular 6: v6.x.x
  • Angular 7: v7.x.x
  • Angular 8: v8.x.x
  • Angular 9: v9.x.x

npm install [email protected] --save

接下來配置全局靜态資源

Angular 6 之前版本 添加到.angular-cli.json檔案中

{
  "options": {
    {
      "assets": [
        { "glob": "**/*", "input": "node_modules/ngx-monaco-editor/assets/monaco", "output": "./assets/monaco/" }
      ],
      ...
    }
    ...
  },
  ...
}
           

Angular 6 之後版本 添加到.angular.json檔案中

{
  "apps": [
    {
      "assets": [
        { "glob": "**/*", "input": "../node_modules/ngx-monaco-editor/assets/monaco", "output": "./assets/monaco/" }
      ],
      ...
    }
    ...
  ],
  ...
}
           

Angular 子產品檔案中配置

DiffEditorModule

import { NgModule } from '@angular/core';
import { DiffEditorRoutingModule } from './diff-editor-routing.module';
import { DiffEditorComponent } from './diff-editor.component';
import { NgZorroAntdModule } from 'ng-zorro-antd';
import { CommonModule } from '@angular/common';
import { ClipboardModule } from 'ngx-clipboard';
import { FormsModule } from '@angular/forms';
import { MonacoEditorModule } from 'ngx-monaco-editor';

@NgModule({
  imports: [
    CommonModule,
    DiffEditorRoutingModule,
    NgZorroAntdModule,
    ClipboardModule,
    FormsModule,
    MonacoEditorModule.forRoot(),
  ],
  declarations: [DiffEditorComponent],
  exports: [DiffEditorComponent]
})
export class DiffEditorModule { }

           

Monaco Editor 支援選擇文本語言、編輯器主題等等配置,我們同樣在頁面上也支援這些配置項動态配置,結合阿裡的NG-ZORRO架構,完整代碼如下:

<div nz-row [nzGutter]="16">
  <div nz-col class="gutter-row" [nzSpan]="24" *ngIf="isCompared">
    <nz-select [(ngModel)]="selectedLang" class="lang-select ditor-config" (ngModelChange)="onChangeLanguage($event)">
      <nz-option *ngFor="let option of languages" [nzValue]="option" [nzLabel]="option"></nz-option>
    </nz-select>
    <nz-select [(ngModel)]="selectedTheme" class="lang-select ditor-config" (ngModelChange)="onChangeTheme($event)">
      <nz-option *ngFor="let option of themes" [nzValue]="option.value" [nzLabel]="option.name"></nz-option>
    </nz-select>
    <nz-switch class="ditor-config" [(ngModel)]="switchValue" [nzControl]="true" (click)="onChangeInline()" nzCheckedChildren="開啟内聯差異"
      nzUnCheckedChildren="關閉内聯差異"></nz-switch>
    <button class="ditor-config" nz-button nzType="primary" (click)="onClear()">傳回</button>
  </div>
  <div nz-col class="gutter-row diff-editor-row" [nzSpan]="24" *ngIf="isCompared">
    <ngx-monaco-diff-editor style="height: 100%" [options]="options" [originalModel]="originalModel" [modifiedModel]="modifiedModel">
    </ngx-monaco-diff-editor>
  </div>
  <div nz-col class="gutter-row" [nzSpan]="24" *ngIf="!isCompared">
    <button class="ditor-config" nz-button nzType="primary" (click)="onCompare()">比對文本</button>
  </div>

  <div nz-col class="gutter-row" [nzSpan]="12" *ngIf="!isCompared">
    <textarea nz-input placeholder="請輸入比對文本" [nzAutosize]="{ minRows: 10, maxRows: 29 }" [(ngModel)]="text1"></textarea>
  </div>
  <div nz-col class="gutter-row" [nzSpan]="12" *ngIf="!isCompared">
    <textarea nz-input placeholder="請輸入比對文本" [nzAutosize]="{ minRows: 10, maxRows: 29 }" [(ngModel)]="text2"></textarea>
  </div>
</div>
           
import { Component, Input, OnInit, Output } from '@angular/core';
import { DiffEditorModel } from "ngx-monaco-editor";
import { Title } from '@angular/platform-browser';

@Component({
  selector: 'app-diff-editor',
  templateUrl: './diff-editor.component.html',
  styleUrls: ['./diff-editor.component.less']
})
export class DiffEditorComponent implements OnInit {

  constructor(private titleService: Title) {
  }

  text1 = "";
  text2 = "";
  selectedLang = "plaintext";
  selectedTheme = "vs";
  languages = [
    "bat",
    "c",
    "coffeescript",
    "cpp",
    "csharp",
    "csp",
    "css",
    "dockerfile",
    "fsharp",
    "go",
    "handlebars",
    "html",
    "ini",
    "java",
    "javascript",
    "json",
    "less",
    "lua",
    "markdown",
    "msdax",
    "mysql",
    "objective-c",
    "pgsql",
    "php",
    "plaintext",
    "postiats",
    "powershell",
    "pug",
    "python",
    "r",
    "razor",
    "redis",
    "redshift",
    "ruby",
    "rust",
    "sb",
    "scss",
    "sol",
    "sql",
    "st",
    "swift",
    "typescript",
    "vb",
    "xml",
    "yaml"
  ];
  themes = [
    {
      value: "vs",
      name: "Visual Studio"
    },
    {
      value: "vs-dark",
      name: "Visual Studio Dark"
    },
    {
      value: "hc-black",
      name: "High Contrast Dark"
    }
  ];

  options = {
    theme: "vs",
    language: "plaintext",
    readOnly: true,
    renderSideBySide: true
  };
  originalModel: DiffEditorModel = {
    code: "",
    language: "plaintext"
  };

  modifiedModel: DiffEditorModel = {
    code: "",
    language: "plaintext"
  };

  switchValue = false;
  isCompared = false;

  public ngOnInit() {
    this.titleService.setTitle('碼加線上工具 - 文本比對');
  }

  onChangeLanguage(language) {
    this.options = Object.assign({}, this.options, {
      language: language
    });
    this.originalModel = Object.assign({}, this.originalModel, {
      language: language
    });
    this.modifiedModel = Object.assign({}, this.modifiedModel, {
      language: language
    });
  }
  onChangeTheme(theme) {
    this.options = Object.assign({}, this.options, { theme: theme });
  }

  onChangeInline() {
    this.options = Object.assign({}, this.options, {
      renderSideBySide: this.switchValue
    });
    this.switchValue = !this.switchValue;
  }

  onCompare() {
    this.originalModel = Object.assign({}, this.originalModel, {
      code: this.text1
    });
    this.modifiedModel = Object.assign({}, this.modifiedModel, {
      code: this.text2
    });
    this.isCompared = true;
  }
  onClear() {
    this.isCompared = false;
  }
}

           

運作結果如下:

使用微軟Monaco Editor 編寫代碼比對工具前言環境及元件實作

完美運作

最後推薦一個比較幹淨實用的線上工具 http://tool.codeplus.vip/