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
- 513
 
   
   
  