DevUI It is an open-source front-end solution for enterprise middle and back office products. It advocates the design values of immersion, flexibility and simplicity, advocates designers to serve the real needs and design for most people, and rejects the design that attracts the attention of the public. If you are developing tool products of ToB, DevUI will be a good choice!
introduction
The rich text editor is probably the most complex and widely used component.
It can be said that the rich text editor makes Web data entry full of infinite imagination. If there are only text only data entry components such as text box and drop-down box, the data entry ability of the Web will be greatly limited. We will not be able to insert rich text content such as pictures and videos on the Web page, let alone custom content.
Rich text editor makes Web content editing easier and more efficient. We can insert almost any content you want to insert in the rich text editor, including pictures, videos, hyperlinks, formulas and code blocks. We can even insert super complex custom content such as tables, ppts, mind maps and even 3D models.
The scene of rich text editor can be seen everywhere on the Web. Rich text is required for writing articles, comments, feedback and recording demand lists.
Combined with the practice of DevUI team in rich text components, this paper shares with you the things about Quill rich text editor, from the use scenario, technology selection, to the extension of Quill, and the basic principles of Quill.
This paper mainly consists of the following parts:
- Usage scenario of rich text editor
- Technology selection
- Why did we choose Quill
- How to extend Quill
- Quill Fundamentals
The following content comes from Kagol's speech at Huawei HWEB big front-end technology sharing meeting.
Usage scenario of rich text editor
- Blog post
- Wiki entries
- Work item description
- Test case steps
- Feedback
- comment
- ...
Technology selection
Our needs:
- Open source protocol friendly
- Angular frame or frame independent
- Flexible and scalable
- Supports inserting / editing tables and pictures
- Rich plug-ins and good ecology
Type selection analysis
- First, exclude ueditors that are not maintained officially
- Then exclude the draft.net exclusive to the React framework JS and Slate
- Then exclude CKEditor, which is unfriendly to the open source protocol
- Due to our rich business scenarios and the need for rich text insertion / editing table functions, we also need to exclude Trix that does not support tables, Etherpad and Prosemirror that weakly support tables, and TinyMCE that charges for table functions
- Finally, only Quill and wangEditor are available. wangEditor is not as scalable and ecological as Quill, so Quill is finally selected as the base of rich text components
Why Quill?
- BSD agreement, business friendly
- The document is detailed and easy to use
- API driven, good scalability
- Rich plug-ins and good ecology
Document details
Document: https://quilljs.com/
Introduce Quill's API:
Describes how to extend Quill:
Get started
- Install Quill: npm i quill
- Import style: @ import 'quill / dist / quill snow. css';
- Import Quill: import Quill from 'quill';
- Initialize Quill: new Quill ('#editor', {theme: 'Snow'});
design sketch:
API driven, good scalability
Rich plug-ins and good ecology
Extend Quill
Insert label
For example, I want to insert labels in the editor
Upload attachments
For example, I want to insert an attachment in the editor
Insert expression
For example, I want to insert an expression in the editor
Similar comments: https://www.yuque.com/yuque/blog/sguhed
Personality segmentation line
For example, I want to insert the personalized dividing line of station B
Hyperlink card
For example, I want to insert a hyperlink card like Zhihu
How to insert expressions?
Let's start with how to insert expressions and see how to insert custom content in Quill.
To insert an expression in Quill, you only need the following four steps:
- Step 1: Customize Toolbar Buttons
- Step 2: customize the content of EmojiBlot
- Step 3: register EmojiBlot in Quill
- Step 4: call Quill's API to insert the expression
Step 1: Customize Toolbar Buttons
const quill = new Quill('#editor', { theme: 'snow', modules: { // Configure toolbar module toolbar: { container: [ ..., [ 'emoji' ] ], // Add a button handlers: { // Add button processing logic emoji() { console.log('Insert expression'); } } }, } });
Add icons to toolbar buttons
// Extend Quill's built-in icons configuration const icons = Quill.import('ui/icons'); icons.emoji = '<svg>...</svg>'; // The svg of the icon can be copied from the iconfont website
The effect is as follows:
There is already an emoticon button on the toolbar, which can respond to mouse click events. The next step is to write the specific logic of inserting emoticons, which involves Quill's knowledge of custom content.
Step 2: customize the content of EmojiBlot
The blog in Quill is an ordinary ES6 Class. The difference between expression and picture lies in:
Quill's built-in image format does not support custom width and height, and the expression we want to insert needs a specific width and height.
Therefore, we can extend it based on Quill's built-in image format.
emoji.ts
import Quill from 'quill'; const ImageBlot = Quill.import('formats/image'); // Extend Quill's built-in image format class EmojiBlot extends ImageBlot { static blotName = 'emoji'; // Define the name of the custom blog (must be globally unique) static tagName = 'img'; // Label name of custom content // Create a DOM node for custom content static create(value): any { const node = super.create(value); node.setAttribute('src', ImageBlot.sanitize(value.url)); if (value.width !== undefined) { node.setAttribute('width', value.width); } if (value.height !== undefined) { node.setAttribute('height', value.height); } return node; } // Return options data static value(node): any { return { url: node.getAttribute('src'), width: node.getAttribute('width'), height: node.getAttribute('height') }; } } export default EmojiBlot;
Step 3: register EmojiBlot in Quill
With EmojiBlot, to insert it into Quill editor, you also need to register this ES6 class in Quill.
import EmojiBlot from './formats/emoji'; Quill.register('formats/emoji', EmojiBlot);
Step 4: call Quill's API to insert the expression
After EmojiBlot is registered in Quill, Quill can recognize it and call Quill's API to insert it into the editor.
emoji(): void { console.log('Insert expression'); // Gets the current cursor position const index = this.quill.getSelection().index; // Insert emoji (blotName) at the current cursor this.quill.insertEmbed(index, 'emoji', { url: 'assets/emoji/good.png', width: '64px', }); },
design sketch
Demo source code
Source code link: https://gitee.com/kagol/quill-demo
Also welcome to follow the official website of our DevUI component library to learn more interesting and practical open source components!
DevUI official website: https://devui.design
Quill Fundamentals
Finally, let's talk about the basic principle of Quill.
Basic principles
- Delta data model is used to describe the rich text content and its changes to ensure the predictability of behavior
- DOM is abstracted through parsment to ensure platform consistency
- Monitor the changes of DOM nodes through rotation observe and synchronize the changes of DOM to the Delta data model
How does Quill express editor content?
Delta data model
Delta data model is used to describe the rich text content and its changes
Delta is a subset of JSON and contains only one ops attribute. Its value is an array of objects. Each array item represents an operation on the editor (based on the empty initial state of the editor).
{ "ops": [ { "insert": "Hello " }, { "insert": "World", "attributes": { "bold": true } }, { "insert": "\n" } ] }
Modify editor content
For example, we change the bold "World" to the red text "World". This action is described as follows with Delta:
{ "ops": [ { "retain": 6 }, { "retain": 5, "attributes": { "color": "#ff0000" } } ] }
It means: keep the first 6 characters of the editor, that is, keep "Hello" and the next 5 characters "World", and set these characters to the font color of "#ff0000".
Delete editor content
What if you want to delete "World"?
{ "ops": [ { "retain": 6 }, { "delete": 5 } ] }
That is: keep the first 6 characters ('Hello ') and delete the next 5 characters ('World')
How does Quill render content?
The basic principle of rendering rich text content: traverse the Delta array and apply (insert / format / delete) the content described in it to the editor one by one.
For details, please refer to DevUI column:
Quill's content rendering mechanism
How does Quill extend the capabilities of the editor?
How to extend Quill:
- Expand the content of the editor by customizing the format of blog
- Extend the functions of the editor by customizing the module
For details, please refer to DevUI column:
Modular mechanism of Quill, a modern rich text editor
THANK YOU!