Rich text / foldkit-richtext-dom
Sixty seconds: an editor on a page
ts
import { Bundle } from 'foldkit-bundle'
import * as RichText from 'foldkit-richtext'
import * as Runtime from 'foldkit/runtime'
import { editorAt, Model, type ParentMessage } from 'foldkit-richtext-dom/editor-bundle'
// One editor, placed at the host id its view renders, with what it draws and allows.
const body = editorAt('body', {
rendering: RichText.standardRendering,
vocabulary: {
marks: RichText.markRegistry(RichText.standardMarks),
nodes: RichText.nodeRegistry(RichText.standardNodes),
},
placeholder: 'Write something…',
})
const app = Bundle.assemble<Model, ParentMessage>()([body])
const document = RichText.decodeDocument({
version: 1,
children: [
{ type: 'Paragraph', id: 'p', children: [{ type: 'Text', id: 't', text: 'Hello', marks: [] }] },
],
})
Runtime.embed(
Runtime.makeElement({
Model,
container: window.document.getElementById('app')!,
init: () => app.initial({ document }),
update: app.update(),
view: (model, h) => h.main([], [body.view(model, h)]),
}),
)What each part does, and does not do:
editorAt(hostId, placement)records, underhostId, how this editor renders, which marks and kinds its edits may use, and what a blank document shows. It performs no I/O and renders nothing yet. The placement is recorded rather than passed as an arg because it holds functions and schemas, which a Bundle's schema-decoded args cannot carry.Modelis{ document, editor }: the document, and the editor's interaction state beside it (selection, stored marks, undo history, the slash menu's highlight). The document is the parent's; the editor reads it through its Link and never keeps a copy.body.viewrenders one element,<foldkit-richtext id="body">, and mounts the interpreter into it once. Everything inside belongs to this package.- An edit arrives as a Message,
updateruns the command against the vocabulary, the new document lands inmodel.documentin the same transition, and a patch Command then updates the DOM. An edit the vocabulary forbids is refused and changes nothing.