Skip to main content
Your app draws its toolbar, menus, search field and outline. Inkkit tells you what is available through command state, and you act through editor methods that check the generation you pass.

Drive controls from command state

events.commandStateChanged sends a CommandState whenever the selection, document, history, mode, editability, composition or a pending import changes, and once after each load. Use commands to enable controls and caret to show active formatting. Call commandState() to read the same state on demand.
Availability describes the moment it was sent, not a promise. Pass the generation with each call and handle the error. Every entry in commands is false while the editor is read-only, composing or importing an image, and every format and table entry is false in source and TXT modes. CommandState lists every field.

Format text and edit tables

format(command, options?, expectedGeneration?) applies one formatting command to the selection and returns whether anything changed. Headings, lists and quotes toggle: applying the current form turns it off. A link takes the destination from your own prompt:
format('link') without a destination removes the link. A destination that the editor wouldn’t open, such as a javascript: address, throws invalid-argument. table(command, options?, expectedGeneration?) inserts and edits tables. state.table is present when the selection is in a table, with the cell’s row and column and the table’s size:
Both return false, and change nothing, when the command doesn’t apply here. Format commands and Table commands list every command and option.

Bind shortcuts

Inkkit binds undo, redo, block moves and table exit by default. It binds no formatting keys. Pass a keymap at mount, by the same names as the format and table commands, in ProseMirror key notation, where Mod is Command on Apple platforms and Control elsewhere:
setKeymap replaces the whole map, so pass every binding you want each time. An omitted default name returns to its default, and an empty array disables it. A shortcut whose command fails reports the error through events.error. Shortcuts lists every name and default.

Add the slash menu

The slash menu is off by default. Enable it at mount to offer block commands when the person types / on an empty line. Choose the built-in commands with commands, and add your own with customCommands:
Here chooseNoteLink is your own picker, which returns a Markdown link such as [Plans](notes/plans.md). A custom action returns Markdown, which replaces the line that holds the slash as one undo step, after the same preservation checks as any edit. Return undefined to cancel and keep the typed text. The action can be slow without blocking typing. If the document, selection or mode changes before it settles, Inkkit refuses the result and reports stale-document through events.error. See Slash menu for filtering, keys and every built-in command.

Build your own find

For a basic find bar, find(text) selects the next match, and replace and replaceAll replace them. To show a match count, a match list or highlights, search the readable text yourself:
  • textSnapshot() returns the text the person reads, with a snapshotId. Offsets are UTF-16 code units in that text, not Markdown offsets. Search the original string, as the regular expression does, so a case change that alters a string’s length can’t shift the offsets.
  • selectTextRange(range) selects without taking focus or scrolling, so typing stays in your search field. Pass { focus: true, reveal: true } when the person goes to a result.
  • revealTextRange(range) scrolls the range into view and unfolds a folded callout that holds it.
  • replaceTextRange(range, text) replaces one match with literal text as one undo step. It throws invalid-range for a range that crosses a block or an embed.
  • textRangesRects(ranges) measures a batch of ranges, for highlights you draw. Rectangles are CSS pixels in the page’s client area.
Any edit, reload or mode change makes the snapshot stale, and a stale range throws stale-document. Search again after each change, including after replaceTextRange. To replace every match, call replaceAll. Readable text and layout has the exact rules.

Keep content clear of overlapping chrome

When a toolbar or search bar floats over the editor, tell Inkkit how much of the scroll container it covers. Reveal, find and heading navigation then keep their target out from under it:
The scroll container must be the root or an ancestor of it. setViewport replaces the previous settings, so pass both fields each time.

Show an outline

headings(expectedGeneration?) returns the document’s headings in order, and navigateHeading(heading) focuses and scrolls to one. Entries go stale when the document, its revision or the mode changes, so refresh the outline when command state reports a new version. headings throws during composition or a pending import, so wait for the next state then:
When the person picks an entry, call editor.navigateHeading(entry). A stale entry throws stale-document; refresh and try again.