API Overview
Everything CallioText exports comes from the single entry point @project-callio/calliotext,
and there are over a hundred exports. This page sorts them into five groups by module, describing each
group's responsibility and boundaries. For item-level detail, use the
TypeDoc reference alongside.
Module layers
The source is organized in layers, more fundamental toward the bottom:
Reading from the bottom up: the lowest layer, core, is pure data. It holds the classes for
first- and second-class concepts, the type definitions of the seven node kinds, and the tree validation
functions. It has no React dependency and no notion of an interface, so any environment can import it,
validating a document on a server for instance.
One layer up sit implbase and uibase, a body of React infrastructure: hooks for
reading the current node and its parameters, the style configuration system, button components with
keyboard navigation support, and the error classes used throughout the library. They do not form an editor
by themselves, but both layers above are built on them.
Above that, editor and printer stand side by side as the cores of the editing
side and the output side. Side by side means mutually independent: the editor does not know how the
document will eventually be typeset, the printer does not know how it was edited, and the two share only
the document tree that core defines. The compiler front-end and back-end analogy from tutorial chapter 1
describes exactly this structure. editor owns the Slate wrapper, the tree operations and the plugin
system; printer owns two-phase rendering and the renderer protocol.
The top layer, default_implementation, assembles everything below into ready-to-use products:
the complete editor and printer components, the renderer factory functions, the contexter family. This is
the layer the tutorial works with throughout.
Day-to-day use tends to follow the same order, top down: start with the components and factories of default_implementation; when a concept's appearance needs customizing, use the factories' customization points together with the implbase hooks; drop down to editor when modifying documents programmatically or writing plugins; deal with printer's preprocessing machinery when numbering and cross references come in; and core is present all along, since concepts and node types run through everything. The table below is a quick lookup of each layer's responsibilities:
| Layer | Responsibility | Typical use |
|---|---|---|
| core | The pure data layer: concept classes, node type definitions, tree validation. No React dependency. | Defining concepts, persistence, typing |
| editor | The editing side: the Slate wrapper, renderer registration and dispatch, tree operations, the plugin system, editor state hooks. | Custom plugins, custom buttons, programmatic document edits |
| printer | The output side: two-phase rendering (preprocessing plus rendering), the renderer protocol, the types of the preprocessing products. | Custom printer renderers, reference features |
| default_implementation | The defaults: complete editor and printer components, the renderer factory functions, the contexter family. | Where most applications start |
| implbase / uibase | Infrastructure: hooks like useNode and useParameters, the style configuration system, small UI components, error classes. |
Inside custom renderers |
The typical assembly
The structure the tutorial builds in chapters 3 through 5, condensed:
import {
// core: define concepts
FirstClassConcept, SecondClassConcept,
// printer: printing core
Printer,
// editor: editing core
EditorCore,
// default_implementation: components and factories
DefaultEditorComponent, DefaultPrinterComponent,
get_default_editors, get_default_group_renderer,
} from "@project-callio/calliotext"
const printer = new Printer(first_concepts, second_concepts,
printer_renderers, printer_defaults)
const core = new EditorCore({renderers, default_renderers: get_default_editors(), printer})
<DefaultEditorComponent editorcore={core} />
<DefaultPrinterComponent printer={printer} root={tree} />
These few lines condense the wiring between the layers: the concepts defined with core are handed to the Printer for keeping; the Printer is handed to the EditorCore so the editing side can query it; finally the two default components each take the core object of their own side and start working. Every CallioText application has this same skeleton; what varies is the content of the concept lists and the renderers.
Conventions used throughout the library
These conventions recur in every module; keeping them in mind makes the following pages easier to read:
- Renderer dictionaries are indexed by first-class concept name, in the shape
{group: {"primary": renderer}, inline: {...}, ...}: node kind first, first-class concept name second. Nodes whose lookup fails use the per-node-kind default renderers. - Document nodes reference second-class concepts. A node's
conceptfield stores a second-class concept name; thePrinterresolves it to the first-class concept it inherits, which is where renderers and parameter prototypes are found. - Parameters have two forms. Trees store the typed
ParameterList(shaped{type, val}); rendering code receives the processedProcessedParameterList, in which second-class overrides are applied, function-typed parameters are evaluated, and the type wrappers are stripped, leaving plain values. - Naming style. Functions and methods are snake_case (
get_root); classes and components are PascalCase (EditorCore). A few exports keep historical spellings, notablyget_deafult_group_editor_with_appbarand the module nameintermidiate; copy them as they are.