• Official git: github.com/quilljs/qui…
  • Official document: quilljs.com/
  • 英 文 名 称 : Kang-bing-kui.gitbook. IO /quill/

The editor is a serious editor, but the document is too serious

Some basic usage documentation is ok, and the basic use case code is as follows

import React, { useEffect } from 'react'; import Quill, { QuillOptionsStatic } from 'quill'; import 'quill/dist/quill.snow.css'; import { TranslatorWrapper } from './translator'; const QuillEditor = () => { useEffect(() => { const toolbarOptions = [ [{ header: [false, 1, 2, 3, 4, 5, 6] }], ['bold', 'italic', 'underline', 'strike'], [{ indent: '-1' }, { indent: '+1' }], [{ align: '' }, { align: 'center' }, { align: 'right' }], ['link'], ['image'], ]; Const options: QuillOptionsStatic = {// The boundsDOM element or a CSS selector for the DOM element in which the editor's UI elements (e.g., tooltips) should be included. For now, just consider the left and right bounds. This property is useful, especially in some layouts where no bounds are set, the QL-tooltip overflows the editor and causes occlusion, and sometimes even z-index can't solve occlusion problems in bounds if the layout is determined: document.getElementById('quill_editor') as HTMLElement, debug: 'false', modules: { imageUpload: true, toolbar: toolbarOptions, }, placeholder: '', theme: 'snow', }; const editor = new Quill('#quill_editor', options); setQuillEditor(editor); } []); return ( <TranslatorWrapper> <div id="quill_editor"></div> </TranslatorWrapper> ); }; export default QuillEditor;Copy the code

Basic sample display:

About the Header Chinese display processing in the Quill Toolbar

For styled- Components, add a TranslatorWrapper wrapper to the main container of the Quill editor, and modify the Chinese character by modifying the ::before attribute. If internationalization is needed, it can be done through parameter processing

<TranslatorWrapper>
  <div id="quill_editor"></div>
</TranslatorWrapper>
Copy the code

Style code: translator.js

export const TranslatorWrapper = styled.div` .ql-snow .ql-picker.ql-header .ql-picker-label::before, Ql-snow.ql-picker.ql-header. ql-picker-item::before {content: 'body '; font-size: 14px; } .ql-snow .ql-picker.ql-header .ql-picker-label[data-value='1']::before, Ql-snow.ql-picker.ql-header. ql-picker-item[data-value='1']::before {content: 'title 1'; font-size: 14px; } .ql-snow .ql-picker.ql-header .ql-picker-label[data-value='2']::before, Ql-snow.ql-picker.ql-header. ql-picker-item[data-value='2']::before {content: 'title 2'; font-size: 14px; } .ql-snow .ql-picker.ql-header .ql-picker-label[data-value='3']::before, Ql-snow.ql-picker.ql-header. ql-picker-item[data-value='3']::before {content: 'title 3'; font-size: 14px; } .ql-snow .ql-picker.ql-header .ql-picker-label[data-value='4']::before, Ql-snow.ql-picker.ql-header. ql-picker-item[data-value='4']::before {content: 'title 4'; font-size: 14px; } .ql-snow .ql-picker.ql-header .ql-picker-label[data-value='5']::before, Ql-picker. ql-header. ql-picker-item[data-value='5']::before {content: 'title 5'; font-size: 14px; } .ql-snow .ql-picker.ql-header .ql-picker-label[data-value='6']::before, Ql-snow.ql-picker.ql-header. ql-picker-item[data-value='6']::before {content: 'title 6'; font-size: 14px; } `;Copy the code

Insert the React custom component

Note: The scene here is only for uploading images, so the original upload image button is replaced with a React component directly. Other custom scenes with a new button are not involved this time

Added in the base application code above

import React, { useEffect } from 'react'; .import ImageUploader from './ImageUploader.tsx';

const Image = Quill.import('formats/image');
Image.className = 'img-fluid';
Quill.register(Image, true);
Quill.register('modules/imageUpload', ImageUploader);

const QuillEditor = () = >{...Copy the code

Image upload module Imageuploader.tsx

import React from 'react';
import ReactDOM from 'react-dom';
import Quill, { QuillOptionsStatic } from 'quill';
import _ from 'lodash';
// The React component needs to be injected
import ImgButton from './ImgButton';

interface ImageUploaderInterface {
  quill: Quill;
  options: QuillOptionsStatic;
}
class ImageUploader implements ImageUploaderInterface {
  quill: Quill;
  options: QuillOptionsStatic;
  constructor(quill: Quill, options: QuillOptionsStatic) {
    this.quill = quill;
    this.options = options;

    // Get the toolbar of the Editor
    const toolbar = this.quill.getModule('toolbar');

    // Get the original Upload image button in the Toolbar
    constimageParent = _.toArray(toolbar.container? .children).find((child) = >child? .children[0]? .className ==='ql-image'
    );
    // Overwrite the original button DOM structure
    ReactDOM.render(<ImgButton editor={this.quill} onChange={this.onImageChange} />, imageParent);
  }

  // Pass the image to upload the ImgButton component's callback method, and communicate with the editor
  onImageChange = (src: string) = > {
    this.quill.getSelection(true);
    const index = (this.quill.getSelection() || {}).index || this.quill.getLength();
    this.quill.insertEmbed(index, 'image', src);
  };
}

export default ImageUploader;
Copy the code

Ql-tooltip is blocked when z-index setting is also invalid

Be sure to check that the bounds property is set

 bounds: document.getElementById('quill_editor') as HTMLElement,

Copy the code

Hanlder add

Document provision:

var quill = new Quill('#editor', {
  modules: {
    toolbar: {
      container: '#toolbar',  // Selector for toolbar container
      handlers: {
        'bold': customBoldHandler
      }
    }
  }
});
Copy the code

For toolbars set in array mode, add handler mode as follows

var toolbar = quill.getModule('toolbar');
toolbar.addHandler('bold', customBoldHandler);
Copy the code

Modify the placeholder to add links

UseEffect (() => {document. querySelector('input[data-link]')? .setattribute ('data-link', 'please enter the link HTTP (s)://... '); }, [quillEditor]);Copy the code

The input box in the Quill Snow Link tooltip validates the links entered.

utils.js

import Emitter from 'quill/core/emitter'; import { message } from 'antd'; /** * snowtip tooltip save */ export function snowtipSave () {const {value} = this.textbox; const linkValidityRegex = /^(http|https)/; switch (this.root.getAttribute('data-mode')) { case 'link': { if (! Linkvalidityregex.test (value)) {message.error(' link format error, please enter link HTTP (s)://... '); return; } const { scrollTop } = this.quill.root; if (this.linkRange) { this.quill.formatText(this.linkRange, 'link', value, Emitter.sources.USER); delete this.linkRange; } else { this.restoreFocus(); this.quill.format('link', value, Emitter.sources.USER); } this.quill.root.scrollTop = scrollTop; break; } default: } this.textbox.value = ''; this.hide(); } export function SnowThemeLinkHandler(value) { if (value) { const range = this.quill.getSelection(); if (range == null || range.length === 0) return; let preview = this.quill.getText(range); if (/^\S+@\S+\.\S+$/.test(preview) && preview.indexOf('mailto:') ! == 0) { preview = `mailto:${preview}`; } const { tooltip } = this.quill.theme; tooltip.save = SnowTooltipSave; tooltip.edit('link', preview); } else { this.quill.format('link', false); }}Copy the code

Use cases, based on the underlying use case code

import React, { useEffect } from 'react'; import Quill, { QuillOptionsStatic } from 'quill'; . const SnowTheme = Quill.import('themes/snow'); SnowTheme.DEFAULTS.modules.toolbar.handlers.link = SnowThemeLinkHandler; . const QuillEditor = () => { ...Copy the code