Angular4 中 ckeditor5 插件的使用
Angular4 中 ckeditor5 插件的使用
0 环境、新建项目
环境:
- Windows10
- @Angular/cli@1.4.10(安装 Angular 的过程略过,Angular4 版本比较古老,这也导致项目安装插件及其他操作比较麻烦)
1. ckeditor5 官方用法
基础用法,npm 安装插件后使用
官网教程:
Angular 中用法
npm install @ckeditor/ckeditor5-angular@1.1.0
npm install @ckeditor/ckeditor5-build-classic@20.0.0
首先 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 文件,替换到项目
\node_modules@ckeditor\ckeditor5-build-decoupled-document\build 文件夹下。
此时项目中使用的 ckeditor5 插件里的功能与在线构建的功能一样。
自定义版本的插件为最新版本,需要了解与 Angular 版本是否匹配。
官方用法及 ckeditor5 详细用法不做过多介绍,详细用法请看官方文档,本文着重介绍如何自定义一个插件模块并合并到 ckeditor5。
2. 自定义插件(以一个截屏插件为例)
说明:此插件只是实现在 ckeditor5 的图标栏添加剪辑图标,图标的点击事件则绑定在 Angular 中。即:此插件没有实现图标按钮的点击事件的逻辑部分。
既然是自定义,则需要下载源代码,修改后再重新编译。
npm 安装的插件中,没有源代码,如图:

\node_modules@ckeditor\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 文件夹,找到 node_modules@ckeditor,里面是各种基础插件,用来开发 ckeditor5-build-decoupled-document。
将自己编辑的的插件放入里面 node_modules@ckeditor,然后在 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 项目的 node_modules@ckeditor\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 则可有可无。
<svg viewBox="0 0 1025 1024" xmlns="http://www.w3.org/2000/svg"><path d="M548.576 512q14.848 0 25.728 10.848t10.848 25.728-10.848 25.728-25.728 10.848-25.728-10.848-10.848-25.728 10.848-25.728 25.728-10.848zM720 548.576l289.728 227.424q16 11.424 14.272 32-2.848 20-20 29.152l-73.152 36.576q-7.424 4-16.576 4-9.728 0-17.728-4.576l-394.272-221.152-62.848 37.728q-4.576 2.272-6.848 2.848 8 28 5.728 55.424-4 44-32 84.288t-75.424 70.56q-75.424 48-158.272 48-77.728 0-126.848-44.576-51.424-48-45.152-118.272 4-43.424 32-84t74.848-70.848q75.424-48 158.848-48 47.424 0 86.272 17.728 5.152-7.424 12.576-12.576l69.728-41.728-69.728-41.728q-7.424-5.152-12.576-12.576-38.848 17.728-86.272 17.728-83.424 0-158.848-48-46.848-30.272-74.848-70.848t-32-84q-2.848-33.728 8.864-64.576t36.288-53.152q48.576-45.152 126.848-45.152 82.848 0 158.272 48 47.424 29.728 75.424 70.272t32 84.576q2.272 27.424-5.728 55.424 2.272 0.576 6.848 2.848l62.848 37.728 394.272-221.152q8-4.576 17.728-4.576 9.152 0 16.576 4l73.152 36.576q17.152 9.152 20 29.152 1.728 20.576-14.272 32zM330.848 400q26.272-24 12-61.728t-60.576-66.848q-52.576-33.728-109.728-33.728-42.272 0-64.576 20.576-26.272 24-12 61.728t60.576 66.848q52.576 33.728 109.728 33.728 42.272 0 64.576-20.576zM282.272 825.728q46.272-29.152 60.576-66.848t-12-61.728q-22.272-20.576-64.576-20.576-57.152 0-109.728 33.728-46.272 29.152-60.576 66.848t12 61.728q22.272 20.576 64.576 20.576 57.152 0 109.728-33.728zM384 475.424l54.848 33.152 0-6.272q0-20.576 18.848-32l8-4.576-45.152-26.848-14.848 14.848q-1.728 1.728-5.728 6.272t-6.848 6.848q-1.152 1.152-2.272 2.016t-1.728 1.44zM512 603.424l54.848 18.272 420.576-329.152-73.152-36.576-438.848 246.272 0 64.576-91.424 54.848 5.152 4.576q1.152 1.152 4 3.424 2.272 2.272 6.272 6.848t6.272 6.848l14.848 14.848zM914.272 841.152l73.152-36.576-297.152-233.152-101.152 78.848q-1.152 1.728-7.424 4z"></path></svg>
最重要的是 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() { // ADDEDreturn [ 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 和 classgetCutButton() {$(".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 找到图标并绑定点击事件。
读者感兴趣或有能力可以尝试实现。
相关文章:
Angular4 中 ckeditor5 插件的使用
Angular4 中 ckeditor5 插件的使用 0 环境、新建项目 环境: Windows10Angular/cli1.4.10(安装 Angular 的过程略过,Angular4 版本比较古老,这也导致项目安装插件及其他操作比较麻烦) 1. ckeditor5 官方用法 基础用…...
[python刷题模板] 前缀函数/next数组/kmp算法
[python刷题模板] 前缀函数/next数组/kmp算法 一、 算法&数据结构1. 描述2. 复杂度分析3. 常见应用4. 常用优化二、 模板代码1. 裸前缀函数2. 树上kmp3. 裸kmp三、其他四、更多例题五、参考链接一、 算法&数据结构 1. 描述 前缀函数和next数组基本上是一个东西&#…...
rust 程序设计语言入门(1)
本文是阅读《Rust程序设计语言》的学习记录,配合视频《Rust编程语言入门教程》食用更佳 环境搭建 windows下载rustup_init.exe,点击安装,默认选择msvc的toolchain,一路default即可 解决下载慢的问题,在powershell中修…...
基于蜣螂算法改进的LSTM预测算法-附代码
基于蜣螂算法改进的LSTM预测算法 文章目录基于蜣螂算法改进的LSTM预测算法1.数据2.LSTM模型3.基于蜣螂算法优化的LSTM4.测试结果5.Matlab代码摘要:为了提高LSTM数据的预测准确率,对LSTM中的参数利用蜣螂搜索算法进行优化。1.数据 采用正弦信号仿真数据&…...
Python安全开发——Scapy流量监控模块watchdog
目录 Python蓝队项目说明 (一)Python-蓝队项目-Scapy流量分析 0x01 Scapy参数介绍...
阶段二5_集合ArrayList
一.对象数组 1.对象数组使用案例 需求:将(张三,23)(李四,24)(王五,25) 封装为3个学生对象并存入数组 随后遍历数组,将学生信息输出在控制台 思路…...
十一、Python——匿名函数
1.匿名函数:简化函数定义 2.格式 lambda 参数1,参数2…:运算 3.匿名函数特点 不需要指明函数名定义只有一条语句函数体必须是一个表达式不能显示使用return 4.匿名函数实现求和 s lambda a,b:a b result s(1,2) print(result) # 35.匿名函数作…...
数组常使用的方法
1. join (原数组不受影响)该方法可以将数组里的元素,通过指定的分隔符,以字符串的形式连接起来。返回值:返回一个新的字符串const arr[1,3,4,2,5]console.log(arr.join(-);//1-3-4-2-52. push该方法可以在数组的最后面,添加一个或者多个元素结构: arr.push(值)返回值…...
2023华为软件测试笔试面试真题,抓紧收藏不然就看不到了
一、选择题 1、对计算机软件和硬件资源进行管理和控制的软件是(D) A.文件管理程序 B.输入输出管理程序 C.命令出来程序 D.操作系统 2、在没有需求文档和产品说明书的情况下只有哪一种测试方法可以进行的(A) A.错误推测法测…...
洛谷2月普及组(月赛)
🌼小宇(治愈版) - 刘大拿 - 单曲 - 网易云音乐 OI赛制且难度对标蓝桥杯省赛(😥真难,第三题做了几百年,第四题只敢骗骗分) 花了10块钱🙃 买官网的思路,结果…...
【博学谷学习记录】超强总结,用心分享 | 架构师 Spring源码学习总结
文章目录Spring的循环依赖1.循环依赖的定义&&原因2.循环依赖的场景1.构造器注入引起循环依赖2.Field属性setter注入的循环依赖3.循环依赖解决思路4.三级缓存5.面试题[三级缓存]AOP源码深度剖析概述Spring AOP的前世今生实现机制**JDK 动态代理****CGLIB 代理**流程总结…...
Linux C/C++ timeout命令实现(运行具有时间限制)
Linux附带了大量命令,每个命令都是唯一的,并在特定情况下使用。Linux timeout命令的一个属性是时间限制。可以为任何命令设置时间限制。如果时间到期,命令将停止执行。 如何使用timeout命令 我们将解释如何使用Linux timeout命令 timeout […...
西湖论剑初赛web wp
Node Magical Login 简单的js代码审计。 Flag分成了两部分。 第一部分: 这里就简单的判断了一下user是否等于admin,直接绕过。 第二部分: checkcode ! “aGr5AtSp55dRacer”,让其为真,利用数组绕过。 Flag为&#x…...
【YOLOv8/YOLOv7/YOLOv5系列算法改进NO.55】融入美团最新QARepVGG
文章目录 前言一、解决问题二、基本原理三、添加方法四、总结前言 作为当前先进的深度学习目标检测算法YOLOv8,已经集合了大量的trick,但是还是有提高和改进的空间,针对具体应用场景下的检测难点,可以不同的改进方法。此后的系列文章,将重点对YOLOv8的如何改进进行详细…...
Flutter Windows端打包并生成可安装文件流程
Windows打包 1.首先安装visual Studio 下载地址:https://visualstudio.microsoft.com/zh-hans/ 下载成功后按照下图勾选桌面应用和移动应用下的使用C的桌面开发,勾选右侧安装详细信息中的windows 11/10 sdk 中的任意一个完成安装即可 2.打包Windows …...
凸优化学习:PART3凸优化问题(持续更新)
凸优化问题 凸优化问题的广义定义: 目标函数为凸函数约束集合为凸集 一、优化问题 基本用语 一般优化问题的描述: minimizef0(x)subject to fi(x)⩽0,i1,⋯,mhi(x)0,i1,⋯,p(1)\begin{array}{ll} \operatorname{minimize} & f_0(x) \\ \text { s…...
[ue4] 着色器绑定(Shader Binding)
当我们在ue4中制作了一个美术材质之后,引擎本身会为我们做很多事情,它会把结点翻译为hlsl,生成多个shader变体,并在多个mesh pass中去选择性的调用所需的shader,其中一个重要的过程就是获取shader绑定的数据。 本文将主…...
Rust语言之迭代器
文章目录Rust迭代器Rust迭代器的实现Iterator特型IntoIterator特型for循环与迭代器迭代器类型再看for循环实现自定义迭代器方式一方式二相关参考Rust迭代器 Rust语言内置了迭代器模式,用于实现对一个项的序列进行特定的处理,通常配合for循环使用。当我们…...
TreeSet 与 TreeMap And HashSet 与 HashMap
目录 Map TreeMap put()方法 : get()方法 : Set> entrySet() (重) : foreach遍历 : Set 哈希表 哈希冲突 : 冲突避免 : 冲突解决 ---- > 比散列(开放地址法) : 开散列 (链地址法 . 开链法) 简介 : 在Java中 , TreeSet 与 TreeMap 利用搜索树实现 Ma…...
Java围棋游戏的设计与实现
技术:Java等摘要:围棋作为一个棋类竞技运动,在民间十分流行,为了熟悉五子棋规则及技巧,以及研究简单的人工智能,决定用Java开发五子棋游戏。主要完成了人机对战和玩家之间联网对战2个功能。网络连接部分为S…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
C++.OpenGL (20/64)混合(Blending)
混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...
【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
验证redis数据结构
一、功能验证 1.验证redis的数据结构(如字符串、列表、哈希、集合、有序集合等)是否按照预期工作。 2、常见的数据结构验证方法: ①字符串(string) 测试基本操作 set、get、incr、decr 验证字符串的长度和内容是否正…...
RFID推动新能源汽车零部件生产系统管理应用案例
RFID推动新能源汽车零部件生产系统管理应用案例 一、项目背景 新能源汽车零部件场景 在新能源汽车零部件生产领域,电子冷却水泵等关键部件的装配溯源需求日益增长。传统 RFID 溯源方案采用 “网关 RFID 读写头” 模式,存在单点位单独头溯源、网关布线…...
第6章:Neo4j数据导入与导出
在实际应用中,数据的导入与导出是使用Neo4j的重要环节。无论是初始数据加载、系统迁移还是数据备份,都需要高效可靠的数据传输机制。本章将详细介绍Neo4j中的各种数据导入与导出方法,帮助读者掌握不同场景下的最佳实践。 6.1 数据导入策略 …...
DOM(文档对象模型)深度解析
DOM(文档对象模型)深度解析 DOM 是 HTML/XML 文档的树形结构表示,提供了一套让 JavaScript 动态操作网页内容、结构和样式的接口。 一、DOM 核心概念 1. 节点(Node)类型 类型值说明示例ELEMENT_NODE1元素节点<div>, <p>TEXT_NODE3文本节点元素内的文字COMMEN…...
