天天看點

Angular4 中 ckeditor5 插件的使用Angular4 中 ckeditor5 插件的使用

Angular4 中 ckeditor5 插件的使用

0 環境、建立項目

環境:

  • Windows10
  • @Angular/[email protected](安裝 Angular 的過程略過,Angular4 版本比較古老,這也導緻項目安裝插件及其他操作比較麻煩)

1. ckeditor5 官方用法

基礎用法,npm 安裝插件後使用

官網教程:

Angular 中用法

npm install @ckeditor/[email protected]
npm install @ckeditor/[email protected]
           

首先 npm 安裝兩個插件: ckeditor5-angular 和 ckeditor5-build-decoupled-document(以此版本為示例)。

ckeditor5-angular 經測試版本 v4.0.0 不能在 Angular4 中使用,v1.1.0 可以使用,安裝此版本。

ckeditor5-build-decoupled-document 經測試版本 v34.0.0 無法在 angular4 使用,v20.0.0 可以使用,安裝此版本。

檢視插件版本清單指令如下:

npm view @ckeditor/ckeditor5-angular versions

npm 慢或者報錯,請使用 pnpm 或 cnpm。

官方線上自定義插件用法

首先,還是先安裝 ckeditor5-angular 和 ckeditor5-build-decoupled-document 插件。

再去 ckeditor5 官網,線上建構自定義插件,位址:online-builder,按步驟建立之後下載下傳。

将下載下傳的壓縮檔案解壓,找到 \build\ckeditor.js 檔案,替換到項目

\[email protected]\ckeditor5-build-decoupled-document\build 檔案夾下。

此時項目中使用的 ckeditor5 插件裡的功能與線上建構的功能一樣。

自定義版本的插件為最新版本,需要了解與 Angular 版本是否比對。

官方用法及 ckeditor5 詳細用法不做過多介紹,詳細用法請看官方文檔,本文着重介紹如何自定義一個插件子產品并合并到 ckeditor5。

2. 自定義插件(以一個截屏插件為例)

說明:此插件隻是實作在 ckeditor5 的圖示欄添加剪輯圖示,圖示的點選事件則綁定在 Angular 中。即:此插件沒有實作圖示按鈕的點選事件的邏輯部分。

既然是自定義,則需要下載下傳源代碼,修改後再重新編譯。

npm 安裝的插件中,沒有源代碼,如圖:

Angular4 中 ckeditor5 插件的使用Angular4 中 ckeditor5 插件的使用

\[email protected]\ckeditor5-build-decoupled-document 檔案夾顯示,要使用的檔案是編譯過的 \build\ckeditor.js。

而官網線上建構的版本與 GitHub 位址 下載下傳的版本與上述檔案夾有差別。

線上建構的插件檔案夾結構如圖:

Angular4 中 ckeditor5 插件的使用Angular4 中 ckeditor5 插件的使用

主要多了 src 檔案夾和 webpack.config.js 檔案,src\ckeditor.js 用來配置哪些插件最終應用到插件中,webpack.config.js

配置如何建構插件。

GitHub 下載下傳的檔案解壓後,找到 packages\ckeditor5-build-decoupled-document,與上述線上建構的插件檔案夾結果類似,多了 tests 檔案夾和一些檔案,如圖:

Angular4 中 ckeditor5 插件的使用Angular4 中 ckeditor5 插件的使用

可以複制 packages\ckeditor5-build-decoupled-document 檔案夾用于開發,而不改動源檔案,帶有 webpack.config.js 檔案的檔案夾即是一個項目。

至于用以上哪種開發根據需求選擇,需要自定義後再編寫自己的插件就選擇線上建構的插件,反之選擇 GitHub 版本。

首先介紹一下開發流程:

指令行進入到 ckeditor5-build-decoupled-document(簡稱 document) 目錄下,執行 npm install,安裝開發需要的插件,

此時 document 目錄下出現 node_modules 檔案夾,找到 [email protected],裡面是各種基礎插件,用來開發 ckeditor5-build-decoupled-document。

将自己編輯的的插件放入裡面 [email protected],然後在 ckeditor5-build-decoupled-document\src\ckeditor.js 配置你的插件(根據已有插件配置)。無論編輯插件還是配置都要符合 ckeditor5 的代碼規則。

之後在 packages\ckeditor5-build-decoupled-document 目錄下,執行

npm run build

,如圖:

Angular4 中 ckeditor5 插件的使用Angular4 中 ckeditor5 插件的使用

build 完成後, 在 packages\ckeditor5-build-decoupled-document\build 下找到 ckeditor.js,即編譯好的代碼,

複制放入 Angular 項目的 [email protected]\ckeditor5-build-decoupled-document\build 中即可使用。

下面是代碼的具體實作:

不知道如何開始,可以先看看内部的插件如何編寫的。比較簡單類似的是引用功能(block-quote),甚至可以複制一份将各種檔案名,類名,參數名修改後,加入插件。

首先建立檔案夾:ckeditor5-cutImage,檔案夾位置與結構如圖:

Angular4 中 ckeditor5 插件的使用Angular4 中 ckeditor5 插件的使用
Angular4 中 ckeditor5 插件的使用Angular4 中 ckeditor5 插件的使用

建立并修改 lang 下的檔案,比如 block-quote 插件中的 lang 檔案,此檔案為語言翻譯,

根據已有的,cutImage 中的 lang 檔案夾中的 zh-cn.po 和 contexts.json 檔案内容如下:

# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
#
#                                     !!! IMPORTANT !!!
#
#         Before you edit this file, please keep in mind that contributing to the project
#                translations is possible ONLY via the Transifex online service.
#
#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
#
#                   To learn more, check out the official contributor's guide:
#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
#
msgid ""
msgstr ""
"Language-Team: Chinese (China) (https://www.transifex.com/ckeditor/teams/11143/zh_CN/)\n"
"Language: zh_CN\n"
"Plural-Forms: nplurals=1; plural=0;\n"

msgctxt "Toolbar button tooltip for cutImage."
msgid "cutImage"
msgstr "截屏"
           
{
	"cutImage": "Toolbar button tooltip for cutImage."
}
           

theme 中的檔案類似,最少需要一個 svg 類型的圖示,css 則可有可無。

最重要的是 src 中的檔案 ,對比 block-quote 插件,建立剪輯的檔案,

對比 block-quote 插件,cutimage.js 内容為:

import Plugin from '@ckeditor/ckeditor5-core/src/plugin';

import CutImageEditing from './cutimageediting.js';
import CutImageUI from './cutimageui';

export default class CutImage extends Plugin {
    static get requires() {
        return [ CutImageEditing, CutImageUI ];
    }
}
           

cutimagecommand.js 内容為:

import Command from '@ckeditor/ckeditor5-core/src/command';

export default class CutImageCommand extends Command {
    execute( { value } ) {
        const editor = this.editor;
        const selection = editor.model.document.selection;
    }

    refresh() {
        const model = this.editor.model;
        const selection = model.document.selection;

        const isAllowed = model.schema.checkChild( selection.focus.parent, 'cutImage' );

        this.isEnabled = isAllowed;
    }
}
           

cutimageediting.js 内容為:

import Plugin from '@ckeditor/ckeditor5-core/src/plugin';

import { toWidget, viewToModelPositionOutsideModelElement } from '@ckeditor/ckeditor5-widget/src/utils';
import Widget from '@ckeditor/ckeditor5-widget/src/widget';


export default class CutImageEditing extends Plugin {
	static get requires() {                                                    // ADDED
        return [ Widget ];
    }
	
    init() {}
}
           

cutimageui.js 内容為:

import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';

import cutimageIcon from '../theme/icons/cutimage.svg';
const CUTIMAGE = 'cutImage';

export default class CutImageUI extends Plugin {
		
	static get pluginName() {
		return 'CutImageUI';
	}
	
    init() {
        const editor = this.editor;
		const t = editor.t;

		// Add cutImage button to feature components.
		editor.ui.componentFactory.add( CUTIMAGE, locale => {
			const command = editor.commands.get(CUTIMAGE);
			const view = new ButtonView( locale );

			view.set( {
				label: t( 'cutImage' ),
				icon: cutimageIcon,
				tooltip: true
			} );

			return view;
		} );
    }
}
           

至于 package.json 可做适當修改,CHANGELOG.md、README.md 等可以忽略。

至此此插件(半成品)編輯完成。

回到 ckeditor5-build-decoupled-document\src\ckeditor.js 中配置 cutImage 插件,添加内容如圖:

Angular4 中 ckeditor5 插件的使用Angular4 中 ckeditor5 插件的使用
Angular4 中 ckeditor5 插件的使用Angular4 中 ckeditor5 插件的使用
Angular4 中 ckeditor5 插件的使用Angular4 中 ckeditor5 插件的使用

在 packages\ckeditor5-build-decoupled-document 目錄下,執行

npm run build

建構,等待完成。

注意:ckeditor5 符合 ES6(ECMAScript 2015) 規範,在 webpack.config.js 中配置可以編譯為符合 ES5 規範的檔案。

由于本項目使用的是 ES5 規範,而重新編譯的版本也是符合 ES6 規範的,是以需要稍作配置。

如何配置請看此連結,ES5配置

在 webpack.config.js 配置檔案中,找到 module 下的 rules, 增加内容如下:

module: {
    rules: [
        {},
        {  // 此處為新增部分
            test: /(ckeditor5(?:-[^\/\\]+)?)[\/\\].+\.js$/,
            use: [
                {
                    loader: 'babel-loader',
                    options: {
                        presets: [ require( '@babel/preset-env' ) ]
                    }
                }
            ]
        }
    ]
}
           

Angular 項目中的用法如下:

元件中的 ts 檔案:

import { Component, OnInit, ViewChild, ViewContainerRef } from '@angular/core';

import * as DecoupledEditor from '@ckeditor/ckeditor5-build-decoupled-document';
import '@ckeditor/ckeditor5-build-decoupled-document/build/translations/zh-cn';

@Component({
  selector: 'app-ckeditor-demo',
  templateUrl: './ckeditor-demo.component.html',
  styleUrls: ['./ckeditor-demo.component.css']
})
export class CkeditorDemoComponent implements OnInit {
  @ViewChild('ckeditor', { read: ViewContainerRef }) ckeditor;

  config = {
    toolbar: {
      items: [
        'bold', 'italic', 'underline', 'strikethrough', 'blockQuote', 'mediaEmbed',
        'alignment:left', 'alignment:right', 'imageUpload', 'insertTable', 'cutImage'
      ]
    }
  }
  editor = null;
  ckeditorContent = '';
  decEditor = DecoupledEditor;

  constructor() { }

  ngOnInit() {
  }

  onReady(e) {
    this.editor = e;
    e.ui.getEditableElement().parentElement.insertBefore(
      e.ui.view.toolbar.element,
      e.ui.getEditableElement()
    );
    this.getCutButton();
  }

  // 找到 cutImage 圖示并綁定點選事件
  // 注意:此處通過擷取 class ck-toolbar__items 最後一個子元素找到 cutImage 圖示, 
  // 是因為在類中的 config 參數配置中将 'cutImage' 放在數組 items 的最後, 
  // 由于圖示由 ckeditor 生成, 是以無法在 ckeditor 插件中賦予唯一的 id 和 class
  getCutButton() {
    $(".ck-toolbar__items").children("button:last-child").on('click', () => {
      console.log('cut button clicked!');
    });
  }

  onChange(e) {
    // console.log('onchange', e);
  }
}
           

html 檔案:

<div style="width: 600px;">
  <ckeditor #ckeditor [(editor)]="decEditor" [(ngModel)]="ckeditorContent" [config]="config"
    debounce="500" (ready)="onReady($event)" (change)="onChange($event)">
  </ckeditor>
</div>
           

浏覽器展示結果:

config.toolbar.items 中未添加 ‘cutImage’ 時:

Angular4 中 ckeditor5 插件的使用Angular4 中 ckeditor5 插件的使用

config.toolbar.items 中添加 ‘cutImage’ 時:

Angular4 中 ckeditor5 插件的使用Angular4 中 ckeditor5 插件的使用

點選圖示得到的結果:

Angular4 中 ckeditor5 插件的使用Angular4 中 ckeditor5 插件的使用

由于插件内部實作點選響應事件較為複雜,本插件内部暫時沒有實作圖示點選的響應事件,而是在 Angular 項目中通過 jquery 找到圖示并綁定點選事件。

讀者感興趣或有能力可以嘗試實作。