editor: The Editor
The entire editing side: EditorCore (configuration and node factory), EditorComponent
(the React component and its tree operations), the plugin system, the Slate node utilities, and the editor
state hooks.
EditorCore
EditorCore is the entry object of the editing side: constructed once at startup and shared from then on. Its three constructor arguments match the usage in tutorial chapter 3:
new EditorCore({
renderers: EditorRendererDict, // {group: {first-concept name: renderer}, ...}
default_renderers: EditorDefaultRendererDict, // one default renderer per node kind
printer: Printer, // concept definitions are queried from here
})
Its methods fall into two groups. One is the node factory (the create_ family): create new
nodes by second-class concept name, with idx and placeholder children filled in automatically; use these
rather than hand-written object literals when constructing document content programmatically. The other
group is queries: concept lists, renderers, and the associated printer.
| Method | Description |
|---|---|
create_text(text?) / create_paragraph(text?) | Create text and paragraph nodes |
create_group(name, relation?) | Create a group node by second-class concept name; relation defaults to "separating" |
create_inline(name, text?) / create_support(name) / create_structure(name, relation?) / create_abstract(name) | Create the other concept node kinds, likewise by second-class concept name |
get_sec_concept_list(type) / get_fst_concept_list(type) | List the second- or first-class concept names registered under a node kind |
get_first_renderer(type, fst?) / get_second_renderer(type, sec?) / get_node_renderer(node) | Renderer lookup; falls back to the default renderers |
get_printer() | The associated printer |
get_meta_param(node) | The meta parameters of the node's first-class concept |
EditorComponent
The editor's React component (a class component). In practice you usually mount its wrapper
DefaultEditorComponent (see the defaults page); the two share one set
of props:
interface EditorComponentProps {
editorcore: EditorCore
plugin?: EditorPlugin // custom plugins, stacked on top of the built-ins
init_rootchildren?: AbstractNode["children"] // initial document content
init_rootproperty?: Omit<AbstractNode, "children"> // initial root properties
onUpdate?: (v: any) => void // called on every tree update
onKeyDown? / onKeyUp?: (e) => void // keyboard event callbacks
onFocusChange?: (editor?) => void // called when the cursor position changes
}
| Instance method | Description |
|---|---|
get_root(): AbstractNode | Assemble the current content into a complete document tree; the entry point for saving |
get_core() / get_slate() | The EditorCore, and the underlying Slate editor object |
get_cur_node() / get_cur_concept_node() | The node at the cursor, and the nearest enclosing concept node |
get_node_by_path(path) | Node lookup by path |
new_concept_node(type, sec_name) | Insert a new node of the given second-class concept at the cursor (what the sidebar insert buttons call) |
set_root(property) | Modify the root node's properties |
add_apply_callback(cb) | Register a callback to run after the next Slate apply |
Tree operations
The following methods also live on EditorComponent (mixed in; the source is in treeopmixin).
They are concept-level wrappers over Slate's Transforms, and they are what plugins and custom
buttons mostly deal with:
| Method | Description |
|---|---|
set_node(node, partial) / set_node_by_path(path, partial) | Modify node properties |
auto_set_parameter(node, parameters) | Modify node parameters, handling proxy nodes automatically |
add_nodes(nodes, path) / add_nodes_here(nodes) | Insert nodes at a path, or at the cursor |
add_nodes_before(nodes, target) / add_nodes_after(nodes, target) | Insert before or after a target node |
delete_concept_node(node) / delete_node_by_path(path) / delete_nodes_by_paths(paths) | Delete nodes. The batch version deletes by explicit paths without depending on the current selection (so it works in focus-free contexts such as effects); invalid paths are ignored silently |
unwrap_node(node) | Delete a node but keep its children |
move_concept_node(node, posto) / move_node_by_path(from, to) | Move nodes |
replace_nodes(father, nodes) | Replace all children of a node |
wrap_selected_nodes(node, opts) / wrap_nodes(node, from, to, opts) | Wrap the selection, or a given range, into a new node |
Editor renderers
An editor renderer is at bottom just a React component, receiving the editor, the node, and the child content:
type EditorRenderer<NT extends Node = Node> =
(props: EditorRendererProps<NT>) => React.ReactElement
interface EditorRendererProps<NT> {
editor: EditorComponent
node: NT
children: React.ReactNode // content supplied by Slate; the renderer must output it
}
This is the raw form of an editor renderer. It is rarely written by hand; the factory functions of the default implementation generate renderers with buttons and parameter editing already handled.
The plugin system
A plugin is a function that wraps the Slate editor:
type EditorPlugin =
(editor: EditorComponent, slate: SlateReact.ReactEditor) => SlateReact.ReactEditor
A plugin receives the editor and the Slate editor object and returns the modified Slate editor, matching the plugin pattern of the Slate ecosystem. How to write one is covered in tutorial chapter 7. Related exports:
with_ytext_plugins: the built-in plugin chain, applied automatically when the editor component mounts; you never call it yourself. It contains nine plugins: meta-parameter application (inline and void node handling), four child-constraint plugins, and repair plugins for relation, abstract nodes and parameters.set_normalize_status({initializing?, pasting?})andget_normalize_status(key): read and write the normalization state. The tree passes through intermediate states while a document loads or a paste is processed; custom plugins should skip their checks whileinitializingis true, or they will interfere with loading.
Slate node utilities
Functions for inspecting Slate nodes in plugins and buttons, all prefixed slate_:
| Function | Description |
|---|---|
slate_is_concept(node, type?) | Whether the node is a concept node; the second argument narrows the kind |
slate_is_paragraph / slate_is_text | Paragraph and text checks |
slate_get_node_type(node) | The node's type string |
slate_is_same_concept_node(a, b) | Whether two references point to the same node, compared by idx |
slate_concept_node2path(root, node) | The node's path within the tree |
slate_concept_father(root, node) / slate_concept_father_path(root, path) | The nearest concept ancestor |
slate_idx_to_node(root, idx) | Find a node by idx |
Editor state hooks
For components outside the editor (a toolbar placed elsewhere on the page, say) that need to track editor state:
| Hook | Description |
|---|---|
useEditor() | The current EditorComponent, inside editor renderers; throws outside the editor context |
useCurEditor() | The current editor from anywhere, built on Zustand, refreshing with the editor version |
useCurConceptNode() | The concept node at the cursor; re-renders when it changes |
useCurConceptNodeIdxParam() | Same, but re-renders only when the node's idx or parameters change; cheaper |
useEditorState | The underlying Zustand store, for finer subscription control |