Skip to content
QuireKit
Core docs
Alpha · evolving API
Extension developmentView Markdown ↗

Write a behavior extension

Learn options, storage, commands and lifecycle through a small greeting command.

Suppose your product needs an “Insert greeting” button. It inserts ordinary text without introducing document structure, so use Extension. Start with an Editor containing StarterKit; complete the quick start first if needed.

1. Separate configuration, runtime state and content

DataOwnerSaved in JSON?
Greeting to insertaddOptions(), overridden through .configure()No
Content update count for this sessionaddStorage()No
Inserted textDocument produced by the commandYes

Persistent business data belongs in node or mark attributes, rather than storage. An extension object caches its storage. Create a fresh extension for each Editor to avoid sharing mutable state between editors.

2. Define a typed command

createGreeting() defines insertGreeting(). It delegates to insertContent() with a text node, so even <b>Hello</b> is literal text rather than interpreted HTML.

core/behavior/greeting.tsts

The module augmentation adds the same command type to editor.commands, chain() and can(). Types alone do not install behavior: the extension must be present at runtime.

3. Install and call it

Add to the Editor's extensionsts

On a button click, call editor.chain().focus().insertGreeting().run(). Query availability with editor.can().insertGreeting(). Focus does not establish permission; the application still checks whether the user may edit.

Commands must support can() without requests, storage mutations or DOM effects. This recipe delegates insertion to an existing command and counts accepted updates in onUpdate. Availability queries do not increase the counter.

4. Configuration and inheritance

.configure({ text: 'Welcome' }) changes public options. .extend({ ... }) changes the definition, for example a keyboard binding. When overriding a hook that still needs its inherited behavior, call that hook's this.parent?.().

Install only the final extension. Installing both the original and a same-name extended version causes name, Schema or command conflicts. Higher priority runs earlier; do not use ordering to conceal competing owners of one feature.

5. Verify the result

After can(), both content and storage should be unchanged. Executing the command inserts text; undo removes it. Two Editors with separate createGreeting() results keep separate counters. The counter never appears in downloaded JSON.

Compose complex commands through their supplied tr, commands and chain, without starting a separate editor.commands transaction inside them. A later false result does not roll back earlier writes; see commands and transactions.

Continue with input rules and state plugins, or add persistent nodes and layout. Consult the extension API for complete hooks.

QuireKitQuireKit · Core, plugins and Classic docs