Editor state – inksane
inksane
Introduction

Editor state

Query what is active at the selection, and whether a command would run.

Toolbars, bubble menus, and command palettes need to know what the editor is doing at the current selection. The editor exposes three queries for that.

Check what is active

editor.isActive(name, attrs?) returns true when a mark or block node is active at the current selection.

editor.isActive("bold");
editor.isActive("link", { href: "https://example.com" });
editor.isActive("heading", { level: 1 });

A collapsed selection only counts inside an inline mark, so a caret just after **bold** is not bold. A block node, such as a heading, list, code block, or blockquote, counts when the selection sits on its line or inside it.

These names are provided by registered extensions or BaseKit. A query for an unregistered feature returns false, and its mark range is null:

NameKindActive forAttributes
boldmark**bold** and __bold__—
italicmark*italic* and _italic_—
strikethroughmark~~strikethrough~~—
codemarkInline code—
linkmarkLinkshref
imagemarkImages—
headingnodeATX and Setext headingslevel
bulletListnodeBullet lists—
orderedListnodeOrdered lists—
taskListnodeTask list itemschecked
codeBlocknodeFenced code blocks—
blockquotenodeBlockquotes—
htmlBlocknodeHTML blocks—
horizontalRulenodeHorizontal rules—

Pass an attribute to match a specific state. attrs is matched as a subset, so isActive("link") is true for any link and isActive("link", { href }) only for that one.

Extensions add their own names through the addStateQueries hook.

Find the range of a mark

editor.getMarkRange(name?) returns the range of the active mark around the selection, or null when there is none. Without a name it returns the innermost mark.

const range = editor.getMarkRange("bold");

if (range) {
  console.log(range.from, range.to);
}

Only marks are returned. Block nodes have no range query, because their range is the line or block the selection is already in.

Check whether a command would run

editor.canRun(command, ...args) returns the same boolean as running the command, without changing the editor. Use it to enable or disable a toolbar button.

const canBold = editor.canRun("toggleBold");
const canHeading = editor.canRun("insertHeading", { level: 1 });

The command runs against a projected copy of the current state, so nothing is dispatched and no event fires. An unmounted editor returns false for every command, because commands need the mounted view. An unknown command name throws, which surfaces typos instead of silently disabling a button. Calling it directly, like editor.commands.unknown(), throws the same error.

Next steps