API reference
Generated from the BlockEditorProps and BlockEditorHandle types in the package source, so it always matches what you install.
BlockEditor props#
All props are optional.
| Prop | Type | Default | Description |
|---|---|---|---|
| uploadFile | (file: File, ctx: UploadCallContext) => Promise<string> | — | Custom upload logic. Receives the file and resolves to its public URL. Takes precedence over uploadUrl. |
| uploadUrl | string | — | Endpoint that accepts a multipart/form-data POST with the file in a file field. |
| uploadField | string | file | Field name for multipart file uploads. |
| uploadFieldName | string | — | Backwards-compatible alias for uploadField. |
| mapUploadResponse | UploadResponseMapper | — | Turns the uploadUrl and uploadFromUrl response body (parsed JSON, or text) into the asset URL. Defaults to reading url. |
| uploadFromUrl | string | — | Endpoint that copies a remote asset: a JSON POST of { url, alt?, filename?, kind? } answered with { url }. The server fetches the asset, so it must refuse private and link-local addresses (SSRF), cap the size and check the content type. |
| uploadRemote | (url: string, ctx: UploadCallContext) => Promise<string> | — | Custom re-hosting of a remote asset URL. Takes precedence over uploadFromUrl. |
| uploadHeaders | UploadHeaders | — | Extra request headers (auth) for uploadUrl and uploadFromUrl. |
| rehostImages | "auto" | "off" | ((url: string) => boolean) | — | Which pasted and loaded images to copy to your storage. "auto" (the default) takes every image except those on the page's origin, on hosts earlier uploads returned, and those already re-hosted. Only active when an upload destination is configured. |
| trustedHosts | readonly string[] | ((url: string) => boolean) | — | Hosts whose images are never re-hosted, whatever rehostImages says: "cdn.example.com", "*.example.com" (the domain and its subdomains), an origin such as "https://cdn.example.com", or a predicate on the image URL. |
| uploadConcurrency | number | — | Re-uploads running at once. Defaults to 4. |
| format | "blocks" | "blocks" | Shape of value, initialContent, and onChange. value, defaultValue, and onChange carry HTML strings, parsed and serialized by genesis-editor/parser. value, defaultValue, and onChange carry Markdown strings, converted through the HTML engine. Export is lossy. |
| initialContent | EditorContent | — | Content for the first render (uncontrolled). Ignored when value is set or a persisted document is found. |
| value | EditorContent | — | Controlled content. When it changes to something other than the current document, the editor content is replaced. Controlled HTML. Parsed only when it differs from the HTML the editor last emitted, so echoing it back is free. Controlled Markdown. Parsed only when it differs from the Markdown the editor last emitted, so echoing it back is free. |
| onChange | (blocks: GenesisBlock[], editor: BlockNoteEditor) => void | — | Called after every user edit with the full document. Called with the serialized document, at most every 150 ms while typing. Called with the lossy Markdown export of the document, at most every 150 ms while typing. |
| htmlMode | ParseMode | "clean" | How pasted and loaded HTML is cleaned: "strict" also snaps custom colors to the palette and drops what the editor can't show exactly. |
| baseUrl | string | — | Resolves relative links and image sources in pasted and loaded HTML. |
| clean | CleanOptions | — | Page-furniture removal for pasted and loaded HTML: { noise: false } turns it off; keepSelectors/dropSelectors tune it. |
| cleanupToast | boolean | true | After a paste that removed page furniture, show "Removed N sections · Undo cleanup". |
| meta | MetaOptions | — | Per-block metadata kept from imports (id/lang/dir, quote attributions…). policy: "off" leaves it out of the schema; changing between "off" and the other policies mounts a new editor. |
| embeds | EmbedOptions | — | Which embeds may show (§8): "open" (the default) allows providers plus sandboxed generic iframes; "allowlist" allows providers only, which is recommended for user-generated content. clickToLoad (default false) waits for a click before loading the iframe when set to true. Read once. |
| embedProviders | EmbedProvider[] | — | Extra embed providers (defineEmbedProvider), tried before the built-ins. Read once. |
| linkPreview | LinkPreviewConfig | — | Where link preview cards get their metadata: { endpoint } or { resolve }. With it, a URL pasted on its own line (or added with "/Link preview") becomes a card; without it, URLs stay links. |
| colorContrast | "auto" | "off" | — | "auto" lightens or darkens hex text that would have less than 3:1 contrast with the theme's background. Only the rendering changes; the stored colour stays exact. Palette colours already adapt. |
| onImportReport | (report: FidelityReport) => void | — | Called after HTML, Markdown, or a document file is imported: the initial value, setHTML/setMarkdown/importFile, or a paste from outside the editor. |
| persist | boolean | PersistOptions | — | Opt-in autosave to localStorage. true uses the default key; pass { key } for one key per document. |
| onPersistStatusChange | (status: PersistStatus) => void | — | Reports autosave progress, for a "Saving…/Saved" indicator. Only called when persist is on. |
| onUploadError | (event: UploadErrorEvent) => void | — | Called when an upload fails. The image block also shows the error with a Retry button. |
| theme | EditorTheme | "system" | Color scheme. "system" follows prefers-color-scheme. |
| editable | boolean | true | Set to false for a read-only view. |
| className | string | — | Extra class names for the editor's root element. |
| mobileToolbar | boolean | true | Show the fixed bottom toolbar with block actions on small screens. |
| onConfigureUploads | () => void | — | When set, the upload panel shows a "Configure uploads" link while no upload destination is configured. |
| tools | ToolSelection | — | Which tools to offer: ["heading", "image"], or { heading: { levels: [1, 2] }, bold: true }. Disabled tools are left out of every menu, shortcut, and toolbar, and pasted content falls back to paragraphs. Paragraphs are always on. Defaults to every built-in tool and every plugin. |
| toolbar | ToolbarConfig | false | — | Formatting toolbar items in order, or { items, placement: "fixed" } to pin the toolbar above the editor. false turns it off. Defaults to the built-in items followed by plugin items. |
| plugins | readonly GenesisPlugin[] | — | Plugins from definePlugin, adding blocks, menu items, toolbar items, and shortcuts. |
| googleDrive | GoogleDriveImport | — | Optional hook for "Import from Google Drive" in the slash menu. genesis does not talk to Google; pickFile should return a File your app already obtained. |
| onImportError | (error: DocumentImportError) => void | — | Called when importFile or the slash Import document picker cannot read a file (Pages, unknown type, empty). |
With format="html"
These props take HTML strings instead. initialContent is replaced by defaultValue. See HTML & paste.
| Prop | Type | Default | Description |
|---|---|---|---|
| format | "html" | — | value, defaultValue, and onChange carry HTML strings, parsed and serialized by genesis-editor/parser. |
| defaultValue | string | — | HTML for the first render (uncontrolled). Ignored when value is set or a persisted document is found. |
| value | string | — | Controlled HTML. Parsed only when it differs from the HTML the editor last emitted, so echoing it back is free. |
| onChange | (html: string, info: HtmlChangeInfo) => void | — | Called with the serialized document, at most every 150 ms while typing. |
With format="markdown"
These props take Markdown strings instead. Incoming Markdown is converted to HTML and parsed by the same engine; outgoing Markdown is the lossy export. See Markdown.
| Prop | Type | Default | Description |
|---|---|---|---|
| format | "markdown" | — | value, defaultValue, and onChange carry Markdown strings, converted through the HTML engine. Export is lossy. |
| defaultValue | string | — | Markdown for the first render (uncontrolled). Ignored when value is set or a persisted document is found. |
| value | string | — | Controlled Markdown. Parsed only when it differs from the Markdown the editor last emitted, so echoing it back is free. |
| onChange | (markdown: string, info: HtmlChangeInfo) => void | — | Called with the lossy Markdown export of the document, at most every 150 ms while typing. |
Ref (BlockEditorHandle)#
Pass a ref to <BlockEditor> to get these members.
| Member | Type | Description |
|---|---|---|
| editor | BlockNoteEditor | The underlying BlockNote editor, for anything the props don't cover. |
| focus | () => void | Moves focus into the editor. |
| getBlocks | (options?: { meta?: "keep" | "strip" }) => GenesisBlock[] | The current document. { meta: "strip" } leaves out meta, like stripMeta. |
| setBlocks | (blocks: EditorContent) => void | Replaces the whole document. Counts as an edit for onChange and persistence. |
| getMarkdown | () => string | Lossy Markdown export of the current document. |
| getHTML | (options?: HtmlExportOptions) => string | The current document as HTML, in the format genesis-editor/parser reads back losslessly. Embeds that came from a site's embed code are written back as that code; embeds: "iframe" | "link" and embedScripts change that. |
| setHTML | (html: string) => FidelityReport | Replaces the whole document with parsed HTML and returns the import report. Counts as an edit. |
| setMarkdown | (markdown: string) => FidelityReport | Replaces the whole document with Markdown (via the HTML engine) and returns the import report. Counts as an edit. |
| importFile | (file: File) => Promise<FidelityReport> | Replaces the whole document from a Word, OpenDocument, RTF, HTML, Markdown, or text file. Conversion is lazy-loaded. Apple Pages is refused with a request to export as Word. |
| lastReport | FidelityReport | null | The report from the most recent HTML, Markdown, or document import, or null if nothing was imported yet. |
| clearPersisted | () => void | Removes the persisted copy from localStorage and cancels any pending save. |
| pendingUploads | number | File uploads and image re-uploads still running. |
| uploadsSettled | () => Promise<void> | Resolves once nothing is uploading, so a save can wait for final image URLs. Failed re-uploads count as settled. |
Plugin (definePlugin)#
Fields of the object passed to definePlugin. Only name is required.
| Field | Type | Description |
|---|---|---|
| name | string | Unique name. It is also the plugin's tool name: when the tools prop is set, the plugin is only active if tools includes it. A plugin named like a built-in tool replaces that tool. |
| blocks | Record<string, AnyBlockSpec> | Block types, from createReactBlockSpec(...)() or BlockNote's block specs. |
| styles | Record<string, StyleSpec<any>> | Text styles (marks), keyed by style name. |
| inlineContent | Record<string, InlineContentSpec<any>> | Custom inline content, keyed by type. |
| slashItems | SlashMenuItem[] | ((editor: AnyEditor) => SlashMenuItem[]) | Items added to the slash menu and the "+" menu. |
| toolbarItems | Record<string, ToolbarItem> | Formatting toolbar items, keyed by the name used in the toolbar prop. |
| markdownShortcuts | MarkdownShortcut[] | |
| keyboardShortcuts | Record<string, (editor: AnyEditor) => boolean> | Keyboard shortcuts in ProseMirror notation ("Mod-Shift-c"). Return true when handled. |
| embeds | EmbedProvider[] | Embed providers (defineEmbedProvider), tried before the built-ins. |
| extensions | ExtensionFactoryInstance[] | Lower-level BlockNote extensions (createExtension(...)), for ProseMirror plugins and more. |
Parser (genesis-editor/parser)#
The HTML engine the editor uses, as a standalone entry point with no React or BlockNote dependency.
| parseHTML(html, options?) | Parses HTML into blocks. Returns { blocks, report }. |
| importDocument(source, options?) | Converts a Word, OpenDocument, RTF, HTML, Markdown, or text file to HTML, then parseHTML. Throws DocumentImportError for Pages, empty, or unknown types. |
| detectDocumentFormat(source) | Sniffs the file name, MIME type, and magic bytes. Returns html, markdown, txt, docx, odt, rtf, pages, or unknown. |
| DocumentImportError | Thrown by importDocument. code is pages, unsupported, or empty. |
| parseHTMLAsync(html, options?) | parseHTML, then copies remote images with uploadRemote or an absolute uploadFromUrl before returning. For bulk imports on a server. |
| markdownToHTML(markdown) | Converts CommonMark/GFM to HTML. Does not sanitize; pass the result to parseHTML. |
| parseMarkdown(markdown, options?) | markdownToHTML, then parseHTML. The path setMarkdown and format="markdown" use. |
| parseMarkdownAsync(markdown, options?) | parseMarkdown, then the same image re-hosting as parseHTMLAsync. |
| looksLikeMarkdown(text) / htmlIsMarkdownSource(html, plain) | Paste detection: headings, lists, quotes, fences, tables, Markdown links. A trivial HTML wrapper of the same source counts as Markdown. |
| toHTML(blocks, options?) | Serializes blocks to HTML that parseHTML reads back to the same blocks. embeds: "auto" (default) | "iframe" | "link"; embedScripts adds each site's official script once. |
| stripMeta(blocks) | Removes meta from blocks and their children, for exports that shouldn't carry it. |
| migrateMeta(meta) | Reads meta in any stored form (object or the editor's JSON string) and brings it to META_VERSION. Newer versions are returned untouched. |
| META_VERSION | The meta schema version this build writes (1). |
| isSafeUrl(url, allowDataImage?) | Whether a URL is safe to keep. Relative URLs pass; data: only for raster images when allowed. |
| browserDom | The default DOM adapter, using the browser's DOMParser. |
| PALETTE | The editor's named colors with their text and background hex values. |
| editorColor(value, kind, options?) | Maps any CSS colour to what the editor stores: a palette or swatch name when it's within ΔE2000 3, else lowercase hex. Default-looking colours give undefined. |
| isStoredColor(value, kind, swatches?) | Whether a value is a stored colour: default, a palette or swatch name, #rrggbb, or #rrggbbaa for backgrounds. |
| contrastRatio(a, b) / withContrast(hex, background, min?) | WCAG contrast between two hex colours, and a colour moved toward black or white until it reaches min (3) against background. |
| FONT_SIZES / TOOLBAR_FONT_SIZES / isFontSize(value) / snapFontSize(px) | The stored fontSize steps (6–72 px), the toolbar menu (6–20 px), whether a value is a stored size, and the step for any px size (clamped, ties up). |
| embedRegistry(options?, providers?, context?) | The enabled providers and whether generic iframes are allowed, from an EmbedOptions policy. |
| embedForUrl(url, registry) / embedForIframe(src, registry) | Resolve a page URL or a pasted iframe src to a provider (or sandboxed generic) embed, or null. |
| embedForSnippet(el, registry) / embedForMarkup(root, registry) | A site's embed code (blockquote, div, link or script element), or the first embed in pasted code, as { resolved, fallback, size }. Nothing is run. embedForElement is the deprecated form. |
| embedSnippetHTML(resolved, fallback, registry) / widgetDocument(resolved, fallback, registry) | The site's canonical embed code for export (null without one), and the srcdoc a widget embed is drawn with. |
| snippetLines(el) | An element's readable text as lines, the way embed fallbacks are read. |
| resolveEmbedBlock(props, registry) | How a stored embed block may be drawn: provider frames rebuilt from url, generic ones validated again. |
| BUILT_IN_EMBED_PROVIDERS / defineEmbedProvider / getEmbedFrameSrc / getEmbedScriptSrc | Also exported from genesis-editor, see below. |
| linkedomDom (genesis-editor/parser/linkedom) | A DOM adapter for Node and workers, using the optional linkedom peer. |
| jsdomDom (genesis-editor/parser/jsdom) | A DOM adapter for Node, using the optional jsdom peer. |
| toDomAdapter(dom) | Normalizes a dom option (an adapter, a function returning a Document, or a DOMParser instance or class) into { parse(html) }. Fragments are wrapped in a full document. |
ParseOptions
| Field | Type | Description |
|---|---|---|
| mode | ParseMode | "strict" also snaps custom colors to the palette, keeps only text inside unknown elements, and drops media whose tool is off instead of linking it. |
| tools | ToolSelection | The editor's tools. Content for disabled tools is downgraded so the result is always editable. |
| baseUrl | string | Resolves relative src/href. Falls back to the document's <base href>. |
| dom | DomOption | DOM to parse with. Defaults to the browser's DOMParser. On servers use linkedomDom from genesis-editor/parser/linkedom, jsdomDom from genesis-editor/parser/jsdom, or pass a (html) => Document factory or a DOMParser instance or class. |
| clean | CleanOptions | Page-furniture removal (§9 layers 3–5). |
| trackProvenance | boolean | Stamp top-level blocks with meta.import (at, engine, and baseUrl as origin). |
| maxDataImageBytes | number | data: images larger than this many bytes are removed and counted in images.failed. Defaults to no limit. |
| embeds | EmbedOptions | Which iframes become embeds (§8). Defaults to the "open" policy. Unknown iframes become links under "allowlist". |
| embedProviders | readonly EmbedProvider[] | Extra embed providers, tried before the built-ins. A provider named like a built-in replaces it. |
| maxLength | number | Longer input is truncated, with a warning. Defaults to 10 MB. |
| decodeEscaped | boolean | Decode HTML that arrives JSON-encoded (a quoted JSON string, JSON holding HTML strings, or a string's escaped inside such as <p class=\"x\">a</p>\n), with a warning, instead of showing its escapes as text. Only clear cases are decoded. |
| maxDepth | number | Deeper elements are ignored, with a warning. Defaults to 512. |
export type ToHTMLOptions = {
/** Separator between top-level blocks. Defaults to `"\n"`. */
separator?: string;
/**
* How embeds are written; every form reads back to the same block.
* - `"auto"` (default): embeds that came from a site's embed code (tweets, posts, …) are written back as that
* code, its `<blockquote>` text readable without the script; widget embeds (Gist) always are; others as iframes.
* - `"iframe"`: our own sandboxed iframes (widget embeds still as their snippet).
* - `"link"`: link cards with the fallback text, for email and RSS.
*/
embeds?: "auto" | "iframe" | "link";
/**
* Append each provider's official `<script>` once after its first snippet-form embed, so the code renders
* as on the site when the HTML is published elsewhere. Off by default: the export runs no third-party code.
*/
embedScripts?: boolean;
/** Custom providers, so their embeds are rebuilt on export. Without them, those embeds are written as sandboxed generic iframes. */
embedProviders?: readonly EmbedProvider[];
/** Brand swatches (`tools.colors.swatches`), so colours stored by swatch name export as their hex. */
swatches?: readonly ColorSwatch[];
};export type HtmlBlock = {
type: string;
props?: Record<string, string | number | boolean>;
content?: HtmlInline[] | HtmlTableContent;
children?: HtmlBlock[];
/** Kept source attributes and other metadata (§16). Left out when empty. */
meta?: GenesisMeta;
};export type DropReason = "content" | "noise" | "hidden" | "tracking" | "unsupported" | "embed" | "unsafe";export type WrapperFrame = { tag: string; attrs?: Record<string, string>; group?: string };export type ParseAsyncOptions = ParseOptions &
Pick<UploadConfig, "uploadRemote" | "uploadFromUrl" | "uploadHeaders" | "mapUploadResponse" | "uploadConcurrency" | "trustedHosts"> & {
/** Which image URLs to copy. Defaults to every `http(s)` image not already re-hosted. */
rehostImages?: "auto" | "off" | ((url: string) => boolean);
/** Stops pending uploads; the images they were for keep their original URLs. */
signal?: AbortSignal;
};Types#
Every type is exported from genesis-editor, along with BlockNote's Block, PartialBlock, and BlockNoteEditor.
export type EditorTheme = "light" | "dark" | "system";export type PersistOptions = {
/** localStorage key. Defaults to `"genesis-editor:document"`. Use a distinct key per document. */
key?: string;
/** Delay after the last edit before saving, in milliseconds. Defaults to 400. */
debounceMs?: number;
};export type PersistStatus =
| { status: "idle" }
| { status: "saving" }
| { status: "saved"; savedAt: number }
| { status: "error"; error: unknown };export type UploadErrorEvent =
| {
/** A file the user picked, pasted or dropped. */
kind: "file";
error: Error;
file: File;
/** The image block the file was meant for. */
blockId: string;
/** Uploads the same file to the same block again. */
retry: () => Promise<void>;
}
| {
/** A pasted or loaded image that couldn't be copied to your storage. It keeps its original URL. */
kind: "rehost";
error: Error;
/** The image's original URL. */
url: string;
blockId: string;
/** Tries the re-upload again. */
retry: () => Promise<void>;
};export type UploadResponseMapper = (
body: unknown,
response: Response,
) => string | Promise<string>;export type UploadCallContext = {
/** Aborted when the block is deleted, the editor is destroyed, or the 30 s timeout passes. */
signal: AbortSignal;
/** Reports progress as a fraction from 0 to 1. */
onProgress: (fraction: number) => void;
blockId?: string;
/** `"upload"` for files the user picked, pasted or dropped. */
source: RehostSource | "upload";
/** The kind of asset being transferred. Defaults to the file's MIME type when available. */
kind?: AssetKind;
};export type UploadHeaders = Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>);export type RehostSource = "paste" | "value";export type HtmlChangeInfo = {
/** The document the HTML was serialized from. */
blocks: GenesisBlock[];
/** The report from the most recent HTML or Markdown import (initial value, `setHTML`/`setMarkdown`, or paste), if any. */
report: FidelityReport | null;
editor: BlockNoteEditor;
};export type FidelityReport = {
mode: ParseMode;
/** 0–1: the share of mapped source elements, counting downgrades as half and lost visual styles as a tenth. */
score: number;
/** Top-level blocks produced. */
blocks: number;
/** Elements removed, with their content, and a short text preview of the first one. */
dropped: { tag: string; reason: DropReason; count: number; preview?: string }[];
/** Wrapper elements removed while keeping their content. */
unwrapped: { tag: string; count: number }[];
/** CSS properties that have no equivalent in the editor. `visual` ones lower the score. */
unsupportedStyles: { prop: string; count: number; visual: boolean }[];
/** Content converted to a simpler form, e.g. because its tool is off. */
downgrades: { from: string; to: string; count: number }[];
colors: { palette: number; hex: number };
headings: { promoted: number; dropped: number };
/** Text that kept a font size (`sized`), and sizes outside 6–72 px moved to the nearest end (`clamped`). */
fontSizes: { sized: number; clamped: number };
images: {
total: number;
/** Relative URLs made absolute with `baseUrl` or `<base href>`. */
resolved: number;
/** Relative URLs left as they are because there was no base URL. */
unresolved: number;
/** Images dropped because no usable URL was found, or inline images over `maxDataImageBytes`. */
failed: number;
/** Images copied to the app's storage afterwards (editor re-hosting, `parseHTMLAsync`). */
rehosted: number;
/** Images whose re-upload failed; they keep their original URL. */
rehostFailed: number;
};
/** Embeds created: from a provider, generic (sandboxed) iframes, and iframes the policy turned into links. */
embeds: { provider: number; generic: number; blocked: number };
/** What noise removal took out. Undo it by parsing again with `clean: { noise: false }`. */
cleanup: CleanupSummary;
warnings: string[];
};export type ParseMode = "clean" | "strict";export type CleanOptions = {
/** Set to `false` to skip page-furniture removal (main-content scoping, landmarks, scoring). Defaults to `true`. */
noise?: boolean;
/** Elements matching, inside, or containing these selectors are never removed as noise. */
keepSelectors?: string[];
/** Elements matching these selectors are always removed, even in small pastes. */
dropSelectors?: string[];
/**
* `"collapse"` trims empty paragraphs at the start and end and turns runs of them into one;
* `"keep"` keeps them all, so the editor's own HTML loads back unchanged. Defaults to `"collapse"`.
*/
emptyParagraphs?: "collapse" | "keep";
/** Extra phrases that mark page furniture when they make up most of an element's text. */
phrases?: string[];
};export type CleanupSummary = {
/** Page-furniture sections removed (share bars, related links, navigation…). */
sections: number;
/** Why, e.g. `"share"`, `"related"`, `"navigation"`, in the order first seen. */
labels: string[];
/** Set when noise removal didn't run: `"small"` for pastes under 3 blocks or 500 characters, `"off"` when disabled. */
skipped?: "small" | "off";
};export type GenesisBlock = Block & { meta?: GenesisMeta };export type GenesisMeta = {
v: typeof META_VERSION;
/** HTML attributes kept from the source: `id`, `lang`, `dir`. */
attrs?: Record<string, string>;
wrappers?: WrapperFrame[];
styles?: Record<string, string>;
/** The source element when it isn't implied by the block type, e.g. `"cite"` for a quote attribution. */
source?: { tag: string };
/** Set on imported blocks when `meta.trackProvenance` is on. */
import?: { at: string; engine: string; origin?: string };
/** Integrator and plugin data, namespaced by plugin name. */
ext?: Record<string, unknown>;
};export type MetaOptions = {
/**
* `"keep"` (default) keeps `meta` everywhere. `"strip-on-export"` keeps it in the document and in
* localStorage, but leaves it out of `onChange`, `getBlocks`, `getHTML` and the clipboard. `"off"`
* never stores it.
*/
policy?: MetaPolicy;
/** Stamp imported blocks with `meta.import` (`at`, `engine`, `origin`). Defaults to `false`. */
trackProvenance?: boolean;
};export type StoredDocument = {
v: typeof STORAGE_VERSION;
/** Public block JSON: `meta` is a top-level object on each block. */
blocks: PartialBlock[];
savedAt: number;
};export type ToolSelection =
| readonly (BuiltInToolName | (string & {}))[]
| (BuiltInToolEntry & { [name: string]: boolean | object | undefined });export type ToolOptions = {
heading: {
/** Heading levels to offer. Defaults to all six; the menus show the first three. */
levels?: HeadingLevel[];
};
colors: ColorToolOptions;
};export type ToolbarConfig =
| readonly ToolbarItemName[]
| {
/** Items in order. Defaults to the built-in order followed by plugin items. */
items?: readonly ToolbarItemName[];
/** `"floating"` shows the toolbar over selected text; `"fixed"` pins it above the editor. Defaults to `"floating"`. */
placement?: "floating" | "fixed";
};export type SlashMenuItem = {
/** Unique within the plugin. */
key: string;
title: string;
subtext?: string;
/** Extra search terms. */
aliases?: string[];
/** Menu section. Items without a group go under "Other". */
group?: string;
icon?: ReactNode;
/** Shortcut hint shown on the right, e.g. `"⌘⌥C"`. */
badge?: string;
} & (
| {
/** Block to insert, or to turn the current empty block into. */
block: AnyPartialBlock;
onItemClick?: never;
}
| {
onItemClick: (editor: AnyEditor) => void;
block?: never;
}
);export type MarkdownShortcut = {
/** Matched against the text before the cursor. Anchor with `^` and end with `\s$` to trigger on space. */
find: RegExp;
/** The block to convert to, or a function of the match. Return `undefined` to skip. */
block: AnyPartialBlock | ((match: RegExpMatchArray) => AnyPartialBlock | undefined);
};export type ToolbarButtonProps = {
/** Accessible name and tooltip. */
label: string;
icon: ReactNode;
onClick: (editor: AnyEditor) => void;
/** Shows the button as pressed, e.g. while the selection already has the style. */
isSelected?: (editor: AnyEditor) => boolean;
/** Hides the button for selections it doesn't apply to. */
isVisible?: (editor: AnyEditor) => boolean;
};export type EmbedOptions = {
/** `"open"` (the default) allows providers and sandboxed generic iframes; `"allowlist"` allows providers only. */
policy?: "open" | "allowlist";
/** Provider names to allow. Defaults to all. */
providers?: string[];
/** Generic iframes under the `"open"` policy. Defaults to `true`. */
generic?: boolean;
/**
* Wait for a click before loading the iframe (privacy). Defaults to `false` (load immediately).
* The parser ignores this; it only affects drawing.
*/
clickToLoad?: boolean;
};export type EmbedProvider = {
/** Stored in the block's `provider` prop. */
name: string;
/** Shown in the caption bar, e.g. `"YouTube"`. */
label: string;
/** Page URLs this provider embeds, anchored at `^https?://`. Capture groups go to `toEmbed`. */
match: RegExp[];
/**
* Origins its frames load from: the CSP `frame-src` entries, and the only origins `toEmbed` may return.
* For `render: "widget"` providers, the origins their script loads from.
*/
frameOrigins: string[];
/** Maps a pasted iframe `src` back to the page URL. Without it, the `src` itself is tried against `match`. */
fromIframe?: (src: URL) => string | null | undefined;
/** The site's own embed code (blockquote, div, link or script), read on paste and load and written back on export. */
snippet?: EmbedSnippet;
/** @deprecated Use `snippet`. Reads the page URL from the site's embed markup. */
fromHTML?: (el: Element) => string | null | undefined;
/**
* `"iframe"` (the default): `toEmbed` returns the frame URL. `"widget"`, for sites that offer no frame
* URL: `toEmbed` returns the script URL, and the snippet plus that script run in a sandboxed frame with
* an opaque origin, so the script can't reach the app.
*/
render?: "iframe" | "widget";
/** Keep a pasted iframe's `width`/`height` as the aspect ratio (GIFs, photos), instead of the provider's size. */
pastedSize?: boolean;
toEmbed: (url: string, match: RegExpMatchArray) => EmbedFrame;
};export type EmbedFrame = {
src: string;
/** CSS aspect ratio, e.g. `"16/9"`. Ignored when `height` is set. */
aspectRatio?: string;
/** Fixed height in pixels. */
height?: number;
/** Widest the frame gets, in pixels. */
maxWidth?: number;
/** Permissions policy. Defaults to `PROVIDER_ALLOW` for providers; generic embeds get none. */
allow?: string;
/** Defaults to `PROVIDER_SANDBOX` for providers and `GENERIC_SANDBOX` for generic embeds. */
sandbox?: string;
};export type ColorToolOptions = {
/** Offer the nine palette colours. Default `true`. */
palette?: boolean;
/** Offer document colours and Custom… (any hex). With `false`, pasted hex snaps to a named colour. Default `true`. */
custom?: boolean;
/** Brand colours: lowercase names (`a-z`, `0-9`, `-`) that aren't palette names, and `#rrggbb` values. */
swatches?: readonly ColorSwatch[];
};export type ColorSwatch = { name: string; hex: string };export type GoogleDriveImport = {
/** Opens a picker and returns a file. No OAuth is built in; the host supplies the file. */
pickFile: () => Promise<File | null>;
};Other exports#
| definePlugin(plugin) | Declares a plugin for the plugins prop. See Tools & plugins. |
| defineEmbedProvider(provider) | Declares an embed provider for embedProviders or a plugin's embeds. Validates the name and https frameOrigins. |
| BUILT_IN_EMBED_PROVIDERS | The 33 built-in providers, in match order. |
| getEmbedFrameSrc(options?, providers?) | The CSP frame-src origins for the enabled providers, plus https: when generic embeds are on. |
| getEmbedScriptSrc(options?, providers?) | The CSP script-src origins widget embeds (Gist) load from; their srcdoc frames inherit your policy. |
| GENERIC_SANDBOX / PROVIDER_SANDBOX / PROVIDER_ALLOW / WIDGET_SANDBOX | The sandbox and allow values embeds are drawn with. WIDGET_SANDBOX never includes allow-same-origin. |
| MASTODON_SERVERS | The Mastodon servers whose embed code maps to the mastodon provider; others become sandboxed generic embeds. |
| ToolbarButton | A formatting toolbar button for plugin toolbar items. |
| createReactBlockSpec(config, implementation) | BlockNote's custom block helper, re-exported for plugins. |
| BUILT_IN_TOOLS / BLOCK_TOOLS / INLINE_TOOLS | Tool names, the default for tools. |
| DEFAULT_TOOLBAR | Toolbar item names in their default order. |
| mapResponsePath(path) | Builds a mapUploadResponse that reads a dot path such as data.link. |
| uploadWithConfig(config, file, ctx?) | The upload logic the editor uses, for reuse elsewhere. |
| UploadError | The error uploads throw; status is the HTTP status when there was a response. Network errors and 5xx are retried once when re-hosting. |
| getUploadMode(config) | Returns "custom", "server", or "local" for a config. |
| stripMeta(blocks) / migrateMeta(meta) / META_VERSION | Also exported from genesis-editor/parser, see above. |
| loadStoredDocument(key) | Reads a document saved by persist, migrated to the current StoredDocument format. |
| migrateStoredDocument(value) | Brings a parsed saved value to the current format, or returns null. Saves from before versioning are read as version 1. |
| STORAGE_VERSION | The persist format version (2): public block JSON with top-level meta. |
| clearStoredDocument(key) | Removes a document saved by persist. |
| DEFAULT_PERSIST_KEY | The default persist key, "genesis-editor:document". |
| MAX_LOCAL_UPLOAD_BYTES | The 2 MB limit for the data: URL fallback. |