Rich Editor
Inspired by making quadrats(aka artibox) currently based on slate
w/ quadrats v0
Core
How to define, query and transform json
How to define location
How to cooperate json w/ location
Text
interface Text {
text: string;
}
const someText = {
text: 'a text',
};
Marks
interface Text {
text: string;
[prop: string]: any;
}
const boldText = {
text: 'bold text',
bold: true,
};
The properties of text.
Element
Block, Inline, Void
interface Element {
type: string;
children: Node[];
[prop: string]: any;
}
const paragraphElement = {
type: 'paragraph',
children: [...],
};
const linkElement = {
type: 'link',
children: [...],
url: 'https://example.com',
};

Node
A node schema of json tree
type Node = Element | Text;
Editor
The root node of json tree. Has other information e.g. selection.
interface Editor {
children: Node[];
selection?: Range;
}
Editor & Plugin(with)


controller
Location
Path
type Path = number[]
const editor = {
children: [
{
type: 'paragraph',
children: [
{
text: 'A line of text!',
},
],
},
],
}
The path of text is [0, 0].
Location
Point
interface Point {
path: Path;
offset: number;
}
const start = {
path: [0, 0],
offset: 0,
};
const end = {
path: [0, 0],
offset: 15,
};
Location
Range / Selection
interface Range {
anchor: Point;
focus: Point;
}
Location
Range / Selection - Collapsed

anchor === focus
Location
Range / Selection - Expanded(forwards)
anchor is before focus

Location
Range / Selection - Expanded(backwards)
anchor is after focus

Query


Transform

Normalizing


Currently issues slate has
Not Tree Shakable Api
export const Transforms = {
insertNodes() {
},
wrapNodes() {
},
};
export function insertNodes() {
}
export function wrapNodes() {
}
Currently issues slate has
Too low level apis

Some common queries or transforms need to implemented by ourselves
Currently issues slate has
...etc
Common
All common features a rich editor will have.
Common
Provide all a feature needing
utils/helpers
queries
transforms
...etc
E.g. Blockquote


Platform
The libary/framework to render json and handle events
E.g. React
editor related components
event handlers
hooks
...etc.
React
Rendering


React
event handlers




React - Common
blockquote
extends core
provide renderer and event handlers


React - Widgets
toolbar

React - Common
blockquote - toolbar


React - Serializers
jsx-serializer


Currently issues slate has
Not really care about composition event.
Currently I just hack.




Currently issues slate has
...etc
Usage
Structure
e.g. react
core
common/a
common/b
react/a
react/b
react/a/toolbar
react/b/toolbar
react
react/toolbar
Testing
w/ jsx
Use Jsx w/o React
/** @jsx jsx */
import { jsx } from 'somewhere';
/** @jsx jsx */
import { jsx } from 'somewhere';
const input = (
<editor>
<element>
<cursor />
foo
</element>
</editor>
);
const output = {
children: [
{
children: [
{
text: 'foo'
}
]
}
],
selection: {
anchor: { path: [0, 0], offset: 0 },
focus: { path: [0, 0], offset: 0 },
}
};
Write Json w/ Jsx
/** @jsx jsx */
import { jsx } from '../../../../__fixtures__/hyperscript';
import { isSelectionAtBlockEdge } from './isSelectionAtBlockEdge';
describe('isSelectionAtBlockEdge', () => {
it('collpased on block start', () => {
const input = (
<editor>
<element>
<cursor />
foo
</element>
</editor>
);
expect(isSelectionAtBlockEdge(input)).toBe('start');
});
it('collpased on block center', () => {
const input = (
<editor>
<element>
fo
<cursor />
o
</element>
</editor>
);
expect(isSelectionAtBlockEdge(input)).toBe(undefined);
});
it('collpased on block end', () => {
const input = (
<editor>
<element>
foo
<cursor />
</element>
</editor>
);
expect(isSelectionAtBlockEdge(input)).toBe('end');
});
it('expanded, focus on block start', () => {
const input = (
<editor>
<element>
<focus />
fo
<anchor />
o
</element>
</editor>
);
expect(isSelectionAtBlockEdge(input)).toBe('start');
});
it('expanded, focus on block center', () => {
const input = (
<editor>
<element>
<anchor />
fo
<focus />
o
</element>
</editor>
);
expect(isSelectionAtBlockEdge(input)).toBe(undefined);
});
it('expanded, focus on block end', () => {
const input = (
<editor>
<element>
fo
<anchor />
o
<focus />
</element>
</editor>
);
expect(isSelectionAtBlockEdge(input)).toBe('end');
});
});
Roadmap
Rewrite core
remove slate
make apis friendly
provide all common apis
well testing
PR welcome
Testing common
PR welcome
Rewrite react
remove slate-react
fix composition
PR welcome
Provide other platforms
Someone implement slate-vue but

PR Welcome

Appendix
Enable Tree Shaking
enable flag: usedExports or using production


Enable Tree Shaking
Mark files as side-effect-free


Enable Tree Shaking
No CommonJs, it's a joke



Enable Tree Shaking
Use resolve.mainFields of webpack correctly. Order is important.



Examples
only jsx-serializer, use commonjs from main field

Examples
only jsx-serializer, use es module from module field

References
Q & A
Rich Editor - quadrats
By jjaayy
Rich Editor - quadrats
- 496