中文版文档请见这里

CallioText

CallioText is a library for building structured document editors, built on React, Slate and MUI. This page introduces what it is and why it is worth using, then gives the installation steps and a minimal example that runs as-is.

What is it?

In Word, if you want every theorem in a paper to share a consistent style and carry consecutive numbers, you have to maintain all of that by hand: the styling is applied manually, the numbers are typed manually, and inserting a new theorem in the middle means renumbering everything after it. LaTeX solved this problem long ago: a theorem is written as \begin{theorem}...\end{theorem}, you merely declare that this is a theorem, and the style system takes care of appearance and numbering.

But LaTeX was born for print. It assumes a document's destiny is a stack of paper: numbering finishes its duty on the last page, and a reference, once inked, can never move again. Documents today mostly live on the web, where numbers could carry on across pages by themselves and a reference could unfold the cited passage right under the cursor. None of that is LaTeX's to give. Its input, moreover, is code: as a document grows long, backslashes and braces thicken through the source until it is a chore to read and a chore to change.

CallioText is that kind of editor: it separates structure from appearance the way LaTeX does, edits as easily as Word, and outputs as freely as the web.

How it works

Writing with CallioText involves a division of labor:

Each of the three stages owns its own ground: concept definitions decide which semantics a document may use, writing manipulates only semantics, and typesetting is executed uniformly by rendering rules. To change the styling, changing the concept definitions is enough, without touching a word of the document; to add a new kind of document component, one can even create it inside the running program, no code required. This model is the foundation of the whole library, and tutorial chapter 1 unfolds it in full.

What it gives you

Out of that division of labor come these capabilities:

Each of these capabilities has its chapter in the tutorial: the editing/printing separation is built by hand in chapters 3 and 4, the concept system in chapter 5, numbering and cross references in chapter 6, plugins, persistence and keyboard operation in chapter 7. By the end of the tutorial, every item above is something you built, not just something you heard about. A separate part follows the tutorial, devoted to the default implementation: the default editor's interface, its renderer factories and how to customize them.

To see all of this working before reading any further, open the live demo: a complete editor built with CallioText, preloaded with a short mathematical note, running entirely in your browser.

Installation

CallioText is published on npm:

npm install @project-callio/calliotext

Quick start

Below is a minimal runnable example. The names that appear here are each explained in the tutorial; this example only shows how much code it takes to get an editor running.

import React from "react"
import {
    Printer, EditorCore,
    DefaultEditorComponent,
    get_default_editors,
    get_default_paragraph_renderer,
    useless_renderer_block, useless_renderer_inline, useless_renderer_text,
} from "@project-callio/calliotext"
import "@project-callio/calliotext/calliotext.css"

// No concepts have been defined yet, so these are all empty.
const no_renderers = {group: {}, inline: {}, support: {}, structure: {}, abstract: {}}

// The printer renders documents into typeset output.
const printer = new Printer([], [], no_renderers, {
    group     : useless_renderer_block,
    structure : useless_renderer_block,
    support   : useless_renderer_block,
    abstract  : useless_renderer_block,
    inline    : useless_renderer_inline,
    text      : useless_renderer_text,
    paragraph : get_default_paragraph_renderer({}),
})

// The editor core manages everything the editor needs to know.
const core = new EditorCore({
    renderers: no_renderers,
    default_renderers: get_default_editors(),
    printer,
})

export default function App(){
    return <div style={{height: "100vh", position: "relative"}}>
        <DefaultEditorComponent editorcore={core} />
    </div>
}

This code does three things:

  1. It creates a printer (Printer), the part that turns documents into typeset output. Since no concepts exist yet, it receives empty lists and the plainest possible renderers.
  2. It creates an editor core (EditorCore), which holds the editor's configuration and is connected to the printer so it can look up concept definitions.
  3. It mounts the default editor component (DefaultEditorComponent) on the page.

Open the page and you will see a sheet of paper you can type on. We did not specify any document content, so the editor created an empty document by itself.

An editor without concepts is not much different from a plain text box, though. CallioText starts to show its value once you define concepts. Start with tutorial chapter 1: Core Ideas: Concepts & the Tree.

Documentation map

The documentation has four parts. The tutorial is the main line, progressing chapter by chapter from zero; the default implementation part is devoted to the ready-made interface and is best read after the tutorial; the API docs are organized by module for daily lookup; the TypeDoc reference covers every single export, and details the others skip can be found there:

SectionContent
TutorialBuild a structured editor with theorem numbering and cross references, step by step from zero.
Default ImplementationThe default editor's interface, keyboard scheme, renderer factories and customization points, one by one.
API DocsThe public API organized by module: signatures, purpose and notes.
Full ReferenceItem-by-item reference generated from source comments by TypeDoc (the comments are in Chinese).
Live DemoA complete editor built with CallioText, running in the browser; its source is in the repository's demo/ directory.