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 安裝的插件中,沒有源代碼,如圖:
\[email protected]\ckeditor5-build-decoupled-document 檔案夾顯示,要使用的檔案是編譯過的 \build\ckeditor.js。
而官網線上建構的版本與 GitHub 位址 下載下傳的版本與上述檔案夾有差別。
線上建構的插件檔案夾結構如圖:
主要多了 src 檔案夾和 webpack.config.js 檔案,src\ckeditor.js 用來配置哪些插件最終應用到插件中,webpack.config.js
配置如何建構插件。
GitHub 下載下傳的檔案解壓後,找到 packages\ckeditor5-build-decoupled-document,與上述線上建構的插件檔案夾結果類似,多了 tests 檔案夾和一些檔案,如圖:
可以複制 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
,如圖:
build 完成後, 在 packages\ckeditor5-build-decoupled-document\build 下找到 ckeditor.js,即編譯好的代碼,
複制放入 Angular 項目的 [email protected]\ckeditor5-build-decoupled-document\build 中即可使用。
下面是代碼的具體實作:
不知道如何開始,可以先看看内部的插件如何編寫的。比較簡單類似的是引用功能(block-quote),甚至可以複制一份将各種檔案名,類名,參數名修改後,加入插件。
首先建立檔案夾:ckeditor5-cutImage,檔案夾位置與結構如圖:
建立并修改 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 插件,添加内容如圖:
在 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’ 時:
config.toolbar.items 中添加 ‘cutImage’ 時:
點選圖示得到的結果:
由于插件内部實作點選響應事件較為複雜,本插件内部暫時沒有實作圖示點選的響應事件,而是在 Angular 項目中通過 jquery 找到圖示并綁定點選事件。
讀者感興趣或有能力可以嘗試實作。