CKEditor5入门

2,224 阅读3分钟

前言

本文将简单讲述CKEditor5的配置、使用,以及如何自定义plugin,第一次写文章,如果有错误,希望大家帮忙指出并且多多包涵。

CKEditor5简介

CKEditor经历多年的风吹雨打,已相对较为成熟,而我们要讲的CKEditor5版本不仅在用法上做出了很大的改变,最重要的是已不再兼容IE,因此有IE需求的同学请使用CKEditor4。

官网:ckeditor.com/ckeditor-5

github:github.com/ckeditor/ck…

开始

CKEditor5可以分为Classic editor、Inline editor、Balloon editor、Balloon block editor、Document editor五类,本文以Classic Editor为例:

script引入

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>CKEditor 5 – Classic editor</title>
    <script src="https://cdn.ckeditor.com/ckeditor5/21.0.0/classic/ckeditor.js"></script>
</head>
<body>
    <h1>Classic editor</h1>
    <div id="editor">
        <p>This is some sample content.</p>
    </div>
    <script>
        ClassicEditor
            .create( document.querySelector( '#editor' ), {
                // config
            } )
            .then( editor => {
                // do something
            } )
            .catch( error => {
                console.error( error );
            } );
    </script>
</body>
</html>

npm:

npm install --save @ckeditor/ckeditor5-build-classic

代码如下:

import ClassicEditor from '@ckeditor/ckeditor5-build-classic';

ClassicEditor
    .create( document.querySelector( '#editor' ), {
        // config
    } )
    .then( editor => {
        // get data
        console.log(editor.getData());
        // set data
        editor.setData('<span>test</span>')
    } )
    .catch( error => {
        console.log( error );
    } );

此时,已经可以使用基础的editor了。如代码所示,获取内容和设置内容的方法分别为editor.getData()editor.setData()

Webpack配置

当使用前端框架时,可能需要配置webpack,具体配置详见:

自定义CKEditor

之前引入的包是官方构建好的包,一般可以满足基本需求,但有时需求并不能如你所愿,所以需要自定义CKEditor功能。

安装依赖:

npm install --save @ckeditor/ckeditor5-editor-classic
npm install --save @ckeditor/ckeditor5-essentials
npm install --save @ckeditor/ckeditor5-paragraph
npm install --save @ckeditor/ckeditor5-basic-styles
npm install --save @ckeditor/ckeditor5-image

安装的依赖中第一项'@ckeditor/ckeditor5-editor-classic'为基础Classic editor;后四项为官方提供的plugin(还有很多,详见ckeditor.com/docs/ckedit…)。

代码如下:

import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor';

import Essentials from '@ckeditor/ckeditor5-essentials/src/essentials';
import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic';
import Image from '@ckeditor/ckeditor5-image/src/image';
import ImageCaption from '@ckeditor/ckeditor5-image/src/imagecaption';

ClassicEditor
    .create( document.querySelector( '#editor' ), {
        plugins: [ Essentials, Paragraph, Bold, Italic, Image, ImageCaption ],
        toolbar: [ 'bold', 'italic' ]
    } )
    .then( editor => {
        console.log( 'Editor was initialized', editor );
    } )
    .catch( error => {
        console.error( error.stack );
    } );

此时需要注意引入Classic editor并不是在开始中引入的构建好的@ckeditor/ckeditor5-build-classic,而是@ckeditor/ckeditor5-editor-classic,并且在imprort引用时,并不是全引用,而是@ckeditor/ckeditor5-editor-classic/src/classiceditor,否则都会报“ckeditor-duplicated-modules”的错,这个报错的原因是由于CKEditor中有重复引用的情况。

在这里说一下我碰到的百年难得一遇的坑,在npm安装依赖时,正赶上CKEditor5更新npm包,导致前几个包是20.0.0版本,后安装的是21.0.0,导致了“ckeditor-duplicated-modules”报错,wtf!!!所以大家如果遇到这个错,也检查一下版本,如果版本有问题,建议删除node-modules内文件和package-lock.json,重新执行npm install。

新建plugin

安装依赖

npm install --save @ckeditor/ckeditor5-core
npm install --save @ckeditor/ckeditor5-ui

代码如下:

import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';
import imageIcon from '@ckeditor/ckeditor5-core/theme/icons/image.svg';

class InsertImage extends Plugin {
    init() {
        const editor = this.editor;

        editor.ui.componentFactory.add( 'insertImage', locale => {
            const view = new ButtonView( locale );

            view.set( {
                label: 'Insert image',
                icon: imageIcon,
                tooltip: true
            } );

            // Callback executed once the image is clicked.
            view.on( 'execute', () => {
                const imageUrl = prompt( 'Image URL' );

                editor.model.change( writer => {
                    const imageElement = writer.createElement( 'image', {
                        src: imageUrl
                    } );

                    // Insert the image in the current selection location.
                    editor.model.insertContent( imageElement, editor.model.document.selection );
                } );
            } );

            return view;
        } );
    }
}

合并代码

import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor';

import Essentials from '@ckeditor/ckeditor5-essentials/src/essentials';
import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic';
import Image from '@ckeditor/ckeditor5-image/src/image';
import ImageCaption from '@ckeditor/ckeditor5-image/src/imagecaption';

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

import imageIcon from '@ckeditor/ckeditor5-core/theme/icons/image.svg';

class InsertImage extends Plugin {
    init() {
        const editor = this.editor;

        editor.ui.componentFactory.add( 'insertImage', locale => {
            const view = new ButtonView( locale );

            view.set( {
                label: 'Insert image',
                icon: imageIcon,
                tooltip: true
            } );

            // Callback executed once the image is clicked.
            view.on( 'execute', () => {
                const imageUrl = prompt( 'Image URL' );

                editor.model.change( writer => {
                    const imageElement = writer.createElement( 'image', {
                        src: imageUrl
                    } );

                    // Insert the image in the current selection location.
                    editor.model.insertContent( imageElement, editor.model.document.selection );
                } );
            } );

            return view;
        } );
    }
}

ClassicEditor
    .create( document.querySelector( '#editor' ), {
        plugins: [ Essentials, Paragraph, Bold, Italic, Image, InsertImage, ImageCaption ],
        toolbar: [ 'bold', 'italic', 'insertImage' ]
    } )
    .then( editor => {
        console.log( 'Editor was initialized', editor );
    } )
    .catch( error => {
        console.error( error.stack );
    } );

这就是添加了insertImage plugin最终代码了,实际项目中建议将plugin和editor实现文件分离,这个plugin较为简单,官方建议将plugin拆分为editing和ui两个模块,如果有时间再给大家更新一个有command个widget的plugin以及写plugin的一些细节介绍。

结语

首次发文,水平有限,大家多多批评,虽然我不一定改,hahahahahahahah...