将插件添加到分叉的 ckEditor repo' 不起作用

adding plugin to forked ckEditor repo' not working

我正在尝试向 React/webpack 项目中的 ckEditor 添加调整图像大小和 link 图像功能。

这是我做的!

  1. 分叉的 ckEditor 回购

  2. 克隆 ckEditor 的稳定分支

    git clone -b stable git@github.com:<your-username>/ckeditor5.git

  3. 添加所需的插件 -> 构建 -> 推送

    cd packages/ckeditor5-build-classic

    npm run build

  4. npm install stable branch of forked branch in my project

    npm i git+https://github.com/your_username/ckeditor5.git#stable --save

  5. 在我的项目中导入编辑器class

    import ClassicEditor from 'ckeditor5/packages/ckeditor5-build-classic';

代码

分叉的 ckEditor5 回购 > packages/ckeditor5-build-classic/src/ckeditor.js

// The editor creator to use.
import ClassicEditorBase from '@ckeditor/ckeditor5-editor-classic/src/classiceditor';

import Essentials from '@ckeditor/ckeditor5-essentials/src/essentials';
import UploadAdapter from '@ckeditor/ckeditor5-adapter-ckfinder/src/uploadadapter';
import Autoformat from '@ckeditor/ckeditor5-autoformat/src/autoformat';
import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic';
import BlockQuote from '@ckeditor/ckeditor5-block-quote/src/blockquote';
import CKFinder from '@ckeditor/ckeditor5-ckfinder/src/ckfinder';
import EasyImage from '@ckeditor/ckeditor5-easy-image/src/easyimage';
import Heading from '@ckeditor/ckeditor5-heading/src/heading';
import Image from '@ckeditor/ckeditor5-image/src/image';
import ImageCaption from '@ckeditor/ckeditor5-image/src/imagecaption';
import ImageStyle from '@ckeditor/ckeditor5-image/src/imagestyle';
import ImageToolbar from '@ckeditor/ckeditor5-image/src/imagetoolbar';
import ImageUpload from '@ckeditor/ckeditor5-image/src/imageupload';
import ImageResize from '@ckeditor/ckeditor5-image/src/imageresize';
import ImageResizeEditing from '@ckeditor/ckeditor5-image/src/imageresize/imageresizeediting';
import ImageResizeHandles from '@ckeditor/ckeditor5-image/src/imageresize/imageresizehandles';
import Indent from '@ckeditor/ckeditor5-indent/src/indent';
import Link from '@ckeditor/ckeditor5-link/src/link';
import LinkImage from '@ckeditor/ckeditor5-link/src/linkimage';
import List from '@ckeditor/ckeditor5-list/src/list';
import MediaEmbed from '@ckeditor/ckeditor5-media-embed/src/mediaembed';
import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
import PasteFromOffice from '@ckeditor/ckeditor5-paste-from-office/src/pastefromoffice';
import Table from '@ckeditor/ckeditor5-table/src/table';
import TableToolbar from '@ckeditor/ckeditor5-table/src/tabletoolbar';
import TextTransformation from '@ckeditor/ckeditor5-typing/src/texttransformation';
import CloudServices from '@ckeditor/ckeditor5-cloud-services/src/cloudservices';
import HorizontalLine from '@ckeditor/ckeditor5-horizontal-line/src/horizontalline';

export default class ClassicEditor extends ClassicEditorBase {}

// Plugins to include in the build.
ClassicEditor.builtinPlugins = [
    Essentials,
    UploadAdapter,
    Autoformat,
    Bold,
    Italic,
    BlockQuote,
    CKFinder,
    CloudServices,
    EasyImage,
    Heading,
    Image,
    ImageCaption,
    ImageStyle,
    ImageToolbar,
    ImageUpload,
    ImageResize,
    ImageResizeEditing,
    ImageResizeHandles,
    Indent,
    Link,
    LinkImage,
    List,
    MediaEmbed,
    Paragraph,
    PasteFromOffice,
    Table,
    TableToolbar,
    TextTransformation,
    HorizontalLine,
];

// Editor configuration.
ClassicEditor.defaultConfig = {
    toolbar: {
        items: [
            'heading',
            '|',
            'bold',
            'italic',
            'link',
            'bulletedList',
            'numberedList',
            '|',
            'outdent',
            'indent',
            'horizontalLine',
            '|',
            'uploadImage',
            'blockQuote',
            'insertTable',
            'mediaEmbed',
            'undo',
            'redo',
        ],
    },
    image: {
        resizeUnit: '%',
        resizeOptions: [
            {
                name: 'resizeImage:original',
                value: null,
            },
            {
                name: 'resizeImage:25',
                value: '25',
                icon: 'small',
            },
            {
                name: 'resizeImage:50',
                value: '50',
                icon: 'medium',
            },
            {
                name: 'resizeImage:75',
                value: '75',
                icon: 'large',
            },
        ],
        toolbar: [
            'imageStyle:inline',
            'imageStyle:block',
            'imageStyle:side',
            '|',
            'toggleImageCaption',
            'imageTextAlternative',
            '|',
            'resizeImage',
            'linkImage',
        ],
    },
};

我的项目>../ckeditor.js

import React, { useEffect, useState, useRef } from 'react';
import { makeStyles } from '@material-ui/core/styles';
import { getToken } from '../../helpers/storage';
/* ckEditor */
import CKEditorInspector from '@ckeditor/ckeditor5-inspector';
import { CKEditor } from '@ckeditor/ckeditor5-react';
import ClassicEditor from 'ckeditor5/packages/ckeditor5-build-classic';

const useStyles = makeStyles({
  root: {
    '& .ck-editor__editable': {
      minHeight: 500,
    },
  },
});

function MyCustomUploadAdapterPlugin(editor) {
  // register upload adapter into file repository plugin
  editor.plugins.get('FileRepository').createUploadAdapter = (loader) => {
    return new MyUploadAdapter(loader);
  };
}

class MyUploadAdapter {
  constructor(props) {
    // CKEditor 5's FileLoader instance.
    this.loader = props;
    // URL where to send files.
    this.url =
      process.env.NODE_ENV === 'development'
        ? `${process.env.API_HOST_STRAPI}/upload`
        : `${process.env.API_HOST_STRAPI_PROD}/upload`;
  }

  // Starts the upload process.
  upload() {
    return new Promise((resolve, reject) => {
      this._initRequest();
      this._initListeners(resolve, reject);
      this._sendRequest();
    });
  }

  // Aborts the upload process.
  abort() {
    if (this.xhr) {
      this.xhr.abort();
    }
  }

  // Example implementation using XMLHttpRequest.
  _initRequest() {
    const xhr = (this.xhr = new XMLHttpRequest());
    const token = getToken();

    xhr.open('POST', this.url, true);
    xhr.responseType = 'json';
    xhr.setRequestHeader('Access-Control-Allow-Origin', '*');
    xhr.setRequestHeader('Authorization', `Bearer ${token}`);
  }

  // Initializes XMLHttpRequest listeners.
  _initListeners(resolve, reject) {
    const xhr = this.xhr;
    const loader = this.loader;

    const genericErrorText = (msg) => "Couldn't upload file:" + ` ${msg}.`;

    xhr.addEventListener('error', () => reject(genericErrorText));
    xhr.addEventListener('abort', () => reject());
    xhr.addEventListener('load', () => {
      const response = xhr.response;

      if (!response || response.error) {
        return reject(
          response && response.data
            ? genericErrorText(`(${response.message}) ${response.data.errors[0].message}`)
            : genericErrorText(response.message)
        );
      }

      // If the upload is successful, resolve the upload promise with an object containing
      // at least the "default" URL, pointing to the image on the server.
      resolve({
        default: response[0].url,
      });
    });

    if (xhr.upload) {
      xhr.upload.addEventListener('progress', (evt) => {
        if (evt.lengthComputable) {
          loader.uploadTotal = evt.total;
          loader.uploaded = evt.loaded;
        }
      });
    }
  }

  //repares the data and sends the request.
  _sendRequest() {
    const formData = new FormData();

    this.loader.file.then((result) => {
      formData.append('files', result);
      this.xhr.send(formData);
    });
  }
}

const custom_config = {
  extraPlugins: [MyCustomUploadAdapterPlugin],
};

const Editor = ({ onDataChange, code }) => {
  const classes = useStyles();

  return (
    <div className={classes.root}>
      <CKEditor
        editor={ClassicEditor}
        data={code}
        config={custom_config}
        onReady={(editor) => {
          CKEditorInspector.attach(editor);
        }}
        onChange={(event, editor) => {
          const data = editor.getData();
          onDataChange('code', data);
        }}
        onBlur={(event, editor) => {}}
        onFocus={(event, editor) => {}}
        disabled={false}
      />
    </div>
  );
};

export default Editor;

如我所料

图像工具栏中有 resizeImage 选项和 link图像。

结果

我在图像工具栏中没有看到 resizeImage 或 linkImage。 这是ckeditor inspector的截图。

感谢您提前提出宝贵意见!!

版本

@ckeditor/ckeditor5-react: ^3.0.2
react: ^17.0.2
webpack: ^5.35.1

参考资料

此问题已通过简单地在 package.json 中的依赖项(而非 devDependencies)中添加 git 包并如下更改导入路径来解决。

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