Book to back

As we mentioned in the previous article, we’re going to use Slate as the editor framework for the Markdown editor wySIWYG.

Start by Posting what I’ve done so far:

I strongly recommend Remixicon, with a unified style and a large amount of icon. All the developers who have used it say well, it is suitable for those of us who have poor visual aesthetic.

So far I have completed the wySIWYG for the title and wySIWYG for the table; The picture is now 50 percent complete, and we want to support a variety of functions in the future, such as landscape sliding, nine-grid layout….

Slate.js’s past lives

Introduction of SLATE

Slate.js is a “very lightweight” editor framework. It does not integrate any functions, but only provides a plug-in extension mechanism for developers to implement their desired functions. It is highly pluggable and lightweight. Slatejs has defined a set of data model independent of UI implementation. The slateJS version used in this paper is 0.57.1.

It’s a lot like Angular

To say it’s like Angular is not to say it’s a framework layer, but Slate has gone through a similar journey to Angular, with many of the apis and language choices removed and switched from JavaScript to typescript.

Most of the slateJS editors that can be found on Github are built on the original slateJS: 0.4x.x. Even the official slate.js documentation includes a main version and a 0.47 version to accommodate developers using previous versions.

Introduction to SLATE Architecture

SLATE as an editor framework, its hierarchical design is obvious, including four modules under the warehouse:

  • SLATE: Core, which defines the data model, the way to manipulate the model, and the editor instance itself
  • React: Plugins for DOM rendering and user interaction, including cursors, shortcuts, and more…
  • Slate-history: Provides undo/redo capability as a plug-in
  • Slate-hyperscript: Allows users to create SLATE data using JSX syntax, which is not used in the project, so it will not be introduced here

state(model)

This is the core area of SLATE, and the API it provides is not as comprehensive in the official documentation as it is on Github.

To do a good job, he must sharpen his tools

To build an editor with SLATE, you need to understand its constructs.

The model structure

State creates and stores document content in a tree structure of Node type:

export type Node = Editor | Element | Text

export interface Element {
  children: Node[]
  [key: string]: unknown
}

export interface Text {
  text: string
  [key: string]: unknown
}
Copy the code
  • The Element type contains the children attribute and can be the parent of other nodes
  • Editor can be thought of as a special Element that is both an Editor instance type and the root node of the document tree
  • The Text type is the leaf node of the tree and contains Text information

It does not restrict the data type we pass in, which allows us to extend Node attributes, but the corresponding Node type must contain children. For example, we define a Node of type image:

export const imageNode = (str: string.link: string) :Node= > {
    return {
        type: "image".url: link,
        desc: str,
        children: [{ text: str }]
    }
};

// Trace the value of value in the editor.
const [value, setValue] = useState([
   imageNode('ceshi'.'https://baidu.com'),]as Node[]);
Copy the code

So why does SLATE use a tree structure to describe document content?

  • Rich text documents inherently contain hierarchical information, such as paragraph. Text, etc., using a tree structure to describe it is intuitive to us as developers
  • The text and attribute information are in the same place, which is convenient for us to obtain the attribute information while obtaining the text
  • Convenient recursive operation

editor

We can get the Editor object in real time, as shown in the screenshot:

From the screenshots, we can see that the editor provides children to store our Node nodes, and also provides many global methods for us to use, such as insertNodes to insertNodes, removeNode to delete nodes, and so on

Cursor and selection selection

With the selection selection of model, SLATE’s selection uses Path+offset design.

Path is an array of type number:

export type Path = number[]
Copy the code

It represents a Node and its ancestors, as well as the index in the children array of their respective ancestors:

For example, the figure above is the first element in the first row.

Offset represents the index position of the cursor in the Text string for nodes of type Text.

The Path plus offet form the Point type, which represents a location in the Model.

export interface Point {
  path: Path
  offset: number
}
Copy the code

Two Point types can be combined to form a Range, representing a selection.


export interface Range {
  anchor: Point // Where the selection begins
  focus: Point // Where the selection ends
}

Copy the code

How do I make changes to models –Transforms

Transforms Transforms a number of methods, which are grouped into four categories:

export constTransforms = { ... GeneralTransforms, ... NodeTransforms, ... SelectionTransforms, ... TextTransforms, }Copy the code
  • NodeTransforms: Operations performed on nodes
  • SelectionTransforms: An operation on a selection
  • TextTransforms: Methods used to manipulate text
  • GeneralTransforms: It does not generate operations but processes them. Only this transforms the Model directly. Any other GeneralTransforms will eventually be converted into one of these GeneralTransforms.

You still have to go to the documentation, but this is just a summary, but it’s not really about things like plug-ins.