# Extension API

Authoring hooks, presets, rules and container control contracts.

Signatures come from public package exports. Descriptions are checked against current JSDoc; identifiers retain their original names.

## Extension definitions

These hooks define installation. See [Extension model](/en/concepts/extensions) for composition.

### ExtensionConfig

Declarative hooks shared by Extension, Node and Mark. Unsupported PM schema fields are rejected.

```ts
export interface ExtensionConfig<Options extends object = Record<string, never>, Storage = Record<string, never>> {
    readonly history?: "effects";
    addSourceProvider?(this: ExtensionContext<Options, Storage, () => MsfeSourceProvider>): MsfeSourceProvider;
    readonly name?: string;
    readonly priority?: number;
    readonly requires?: readonly string[];
    addOptions?(this: OptionsContext<Options>): Options;
    addStorage?(this: ExtensionContext<Options, Storage, () => Storage>): Storage;
    addState?(this: ExtensionContext<Options, Storage, () => readonly StateSlot<unknown>[]>): readonly StateSlot<unknown>[];
    addExtensions?(this: ExtensionContext<Options, Storage, () => readonly AnyExtension[]>): readonly AnyExtension[];
    addCommands?(this: ExtensionContext<Options, Storage, () => Partial<RawCommands>>): Partial<RawCommands>;
    addAiCapabilities?(this: ExtensionContext<Options, Storage, () => readonly unknown[]>): readonly unknown[];
    addKeyboardShortcuts?(this: ExtensionContext<Options, Storage, () => Record<string, () => boolean>>): Record<string, () => boolean>;
    addEditingBoundaries?(this: ExtensionContext<Options, Storage, () => readonly EditingBoundaryRule[]>): readonly EditingBoundaryRule[];
    addBlockInput?(this: ExtensionContext<Options, Storage, () => readonly BlockInputRule[]>): readonly BlockInputRule[];
    addInputRules?(this: ExtensionContext<Options, Storage, () => readonly InputRule[]>): readonly InputRule[];
    addPasteRules?(this: ExtensionContext<Options, Storage, () => readonly PasteRule[]>): readonly PasteRule[];
    addSource?(this: ExtensionContext<Options, Storage, () => SourceSpec>): SourceSpec;
    addAttributes?(this: ExtensionContext<Options, Storage, () => Attributes>): Attributes;
    addNodeView?(this: ExtensionContext<Options, Storage, () => MsfeNodeViewRenderer>): MsfeNodeViewRenderer;
    addMarkdownExtensions?(this: ExtensionContext<Options, Storage, () => MarkdownExtension>): MarkdownExtension;
    addProjections?(this: ExtensionContext<Options, Storage, () => readonly MsfeProjection[]>): readonly MsfeProjection[];
    addProjectionLayers?(this: ExtensionContext<Options, Storage, () => readonly ProjectionLayer[]>): readonly ProjectionLayer[];
    addCodeMirrorExtensions?(this: ExtensionContext<Options, Storage, () => CodeMirrorExtension>): CodeMirrorExtension;
    onBeforeCreate?(this: ExtensionContext<Options, Storage>): void;
    onCreate?(this: ExtensionContext<Options, Storage, () => void | (() => void)>): void | (() => void);
    onUpdate?(this: ExtensionContext<Options, Storage, (event: MsfeChangeEvent) => void>, event: MsfeChangeEvent): void;
    onTransaction?(this: ExtensionContext<Options, Storage, (event: TransactionEvent) => void>, event: TransactionEvent): void;
    onSelectionUpdate?(this: ExtensionContext<Options, Storage, (event: TransactionEvent) => void>, event: TransactionEvent): void;
    onFocus?(this: ExtensionContext<Options, Storage, (event: FocusEvent) => void>, event: FocusEvent): void;
    onBlur?(this: ExtensionContext<Options, Storage, (event: FocusEvent) => void>, event: FocusEvent): void;
    onDestroy?(this: ExtensionContext<Options, Storage>): void;
}
```

**history** — Requirement for CM inverse-effect history from advanced backend extensions.

**addSourceProvider** — @returns Prepared source/history authority; this hook must not allocate or connect resources.

**name** — Stable unique name. Inherited if omitted by extend.

**priority** — Higher priorities install first among dependency-ready extensions.

**requires** — Required extension names.

**addOptions** — @returns Default options, optionally composed with this.parent().

**addStorage** — @returns Mutable state allocated separately for every installation.

**addState** — @returns Document-local transaction state slots and their explicit history policies.

**addExtensions** — @returns Child definitions for a preset.

**addCommands** — @returns Curried source commands; nested commands share one draft.

**addAiCapabilities** — @returns Facts describing this extension to the AI core, typed by `@quirekit/ai-contract`;
called only when an AI integration reads them.

**addKeyboardShortcuts** — @returns Keyboard commands keyed by CodeMirror-compatible shortcut names.

**addEditingBoundaries** — @returns Hidden source ownership shared by navigation, selection and native edits.

**addBlockInput** — @returns Pure block-owned Enter behaviors routed through shared guards and atomic history.

**addInputRules** — @returns Bounded source suffix transformations for native typing.

**addPasteRules** — @returns Source transformations confined to the inserted clipboard text.

**addSource** — @returns Source-bound codec. Source remains the only persistence authority.

**addAttributes** — @returns Persisted source fields, defaults and validation; the codec controls exact encoding.

**addNodeView** — @returns Renderer override; inherits the source codec without duplicating it.

**addMarkdownExtensions** — @returns Advanced backend language contributions.

**addProjections** — @returns Advanced backend visual projections.

**addProjectionLayers** — @returns Composable declarative layers with explicit update and layout ownership.

**addCodeMirrorExtensions** — @returns Advanced backend extensions, such as syntax themes.

**onBeforeCreate** — Runs after configuration and state construction, before any editor DOM is mounted.

**onCreate** — @returns Optional disposer, called before onDestroy.

**onUpdate** — @param event - Accepted source change, without full-document serialization.

**onTransaction** — @param event - Every accepted transaction, including selections and effects.

**onSelectionUpdate** — @param event - A transaction whose selection differs from the preceding state.

**onFocus** — @param event - Native editor focus event.

**onBlur** — @param event - Native editor blur event.

**onDestroy** — Runs once on editor disposal, in reverse installation order.

## Base preset

Each entry accepts a definition or false; replace owners instead of duplicating them.

### StarterKitOptions

Per-feature overrides or explicit exclusions, with duplicate owners still diagnosed.

```ts
export interface StarterKitOptions {
    readonly heading?: AnyExtension | false;
    readonly bold?: AnyExtension | false;
    readonly link?: AnyExtension | false;
    readonly codeBlock?: AnyExtension | false;
    readonly image?: AnyExtension | false;
    readonly emphasis?: AnyExtension | false;
    readonly inlineCode?: AnyExtension | false;
    readonly strikethrough?: AnyExtension | false;
    readonly horizontalRule?: AnyExtension | false;
    readonly blockquote?: AnyExtension | false;
    readonly listMarkers?: AnyExtension | false;
    readonly taskItem?: AnyExtension | false;
    readonly table?: AnyExtension | false;
    readonly textLiterals?: AnyExtension | false;
    readonly dataUrlFold?: AnyExtension | false;
}
```

**heading** — Heading descriptor, or false to omit it.

**bold** — Bold descriptor, or false to omit it.

**link** — Link descriptor, or false to omit it.

**codeBlock** — Code block descriptor, including component overrides, or false.

**image** — Image descriptor, including source resolver and component overrides, or false.

**emphasis** — Emphasis descriptor, or false to omit it.

**inlineCode** — Inline code descriptor, or false to omit it.

**strikethrough** — GFM strikethrough descriptor, or false to omit it.

**horizontalRule** — Thematic separator descriptor, or false to omit it.

**blockquote** — Quote body and prefix descriptor, or a host extension with component controls.

**listMarkers** — Native list-prefix descriptor, or false to omit it.

**taskItem** — Task checkbox descriptor, including Vue/React overrides, or false.

**table** — GFM native table presentation, or false to omit it.

**textLiterals** — Prose entity, escape and break presentation, or false to omit it.

**dataUrlFold** — Folds long base64 data URLs into a size pill without changing the source, or false to omit it.

## Source rules

Both rule classes use this configuration. See [Input rules](/en/extensions/input-rules).

### RuleConfig

Source-native rule; unlike a PM input rule, its output is exact Markdown text.

```ts
export interface RuleConfig {
    readonly find: RegExp;
    readonly handler: (context: RuleMatch) => string | null;
}
```

**find** — Pattern matched against the bounded input context.

**handler** — @param context - Match, source coordinates and source access.
@returns Exact replacement or null to preserve the input.

## Container options

Arrays replace defaults. Controls own disclosure UI while source owns the body.

### ContainerOptions

Safe named containers; HTML attributes and executable render functions are not document syntax.

```ts
export interface ContainerOptions {
    readonly types: readonly string[];
    readonly detailsOpen: boolean;
    readonly controls?: ComponentViewRenderer<ContainerControlProps>;
    readonly toggleLabel: (expanded: boolean, title: string) => string;
}
```

**types** — Accepted names; unknown names remain ordinary Markdown.

**detailsOpen** — Initial details view state, reset when a different document is installed.

**controls** — Host component-library control; omitted uses a plain accessible native button.

**toggleLabel** — @param expanded - Current state.
@param title - Literal title or container name.
@returns Localized action.

## Disclosure controls

Components receive view; toggling is source-neutral.

### ContainerControlProps

Source-neutral disclosure control, with no second content or selection owner.

```ts
export interface ContainerControlProps {
    readonly expanded: boolean;
    readonly label: string;
    readonly toggle: () => void;
}
```

**expanded** — Current effective visibility.

**label** — Host-localized accessible action.

**toggle** — Requests a source-neutral view transaction.
