# Classic API

产品装配的公共配置、上下文、动作与资源生命周期。

## 预设和实例

`createClassicEditor(options)` 返回产品实例。`document` 是内容，`preset` 解析模型/视图，`plugins` 声明产品能力，`extensions` 追加普通扩展，`shell` 配置产品界面，`media` / `host` 提供宿主服务。

`instance.editor` 只在已挂载时存在。`instance.update(options)` 单独更新语言、只读和内置预设的主题时保留 Core 与撤销历史；结构设置仍重建 Core/View。自己的 Core 工作区切后端使用 `editor.changeMode()`，语义不同。完整配置与方法见[实例与配置参考](/classic/reference)。

### ClassicEditorPreset

`@quirekit/classic-editor` · AGPL-3.0-only

每个实例独立解析的产品预设，组合扩展、特性、插件与界面默认值。

```ts
export interface ClassicEditorPreset {
    readonly id: string;
    readonly features: ClassicEditorFeatureOptions;
    readonly plugins?: readonly ClassicEditorPlugin[] | undefined;
    readonly theme?: QuireKitTheme | undefined;
    readonly shell?: ClassicEditorShellOptions | undefined;
    readonly ui?: ClassicEditorUiProfileOptions | undefined;
    readonly updatePresentation?: ((context: ClassicEditorPresetPresentationContext) => void) | undefined;
    resolveExtensions(context: ClassicEditorPresetContext): readonly QuireAnyExtension[];
}
```

**id** — 预设的稳定身份。

**features** — 先于实例覆盖项合并的特性默认值。

**plugins** — 先于实例插件安装的默认产品插件。

**theme** — 实例未提供主题时使用的完整主题。

**shell** — 先于实例覆盖项合并的界面默认配置。

**ui** — 动作贡献的最终界面组合。

**updatePresentation** — 在保留会话时刷新主题和语言派生的呈现，不改变 Schema 或正文。context 提供当前 Core、主题、语言与宿主覆盖；缺省时改变主题继续重建。

**resolveExtensions** — 为一次挂载解析普通扩展。
@param context - 特性、主题、视口与后端运行时。
@returns 安装到 Core 的有序扩展集合。

`preset.resolveExtensions(context)` 的结果是普通扩展数组；`preset.plugins` 还需要产品注册表安装。只消费前者时不应宣称已安装预设的文件、许可反馈、链接键盘等产品插件。

自定义 preset 的 `updatePresentation(context)` 用于刷新保留会话的主题与语言派生呈现。它只修改自己拥有的绘制配置，保留宿主显式覆盖，并刷新相应缓存依赖；不能更换 Schema、安装插件或改正文。可以调用公开 `updateClassicEditorPresetPresentation(context)` 复用内置 Canvas/SVG 颜色刷新，再处理自己的扩展。未提供该钩子时，改变主题继续重建 Core。

## 产品插件

### ClassicEditorPlugin

`@quirekit/classic-editor` · AGPL-3.0-only

产品层插件合同，负责界面、服务、快捷键与生命周期；文档修改仍使用 Core 命令。

```ts
export interface ClassicEditorPlugin {
    readonly id: string;
    readonly audience?: ClassicEditorAudience | undefined;
    readonly contributions?: readonly ClassicEditorContribution[] | undefined;
    readonly extensions?: readonly QuireAnyExtension[] | undefined;
    readonly toolbarItems?: readonly (ClassicEditorToolbarControlContribution | ClassicEditorActionToolbarControlContribution)[] | undefined;
    readonly contextMenuItems?: readonly (ClassicEditorContextMenuItemContribution | ClassicEditorActionContextMenuItemContribution)[] | undefined;
    readonly selectionPopupItems?: readonly (ClassicEditorSelectionPopupItemContribution | ClassicEditorActionSelectionPopupItemContribution | ClassicEditorSelectionPopupWidgetContribution)[] | undefined;
    readonly contextualPopupItems?: readonly ClassicEditorContextualPopupItemContribution[] | undefined;
    readonly sidebarPanels?: readonly ClassicEditorSidebarPanelContribution[] | undefined;
    readonly globalSettingsSections?: readonly ClassicEditorGlobalSettingsSectionContribution[] | undefined;
    readonly keyboardShortcuts?: readonly ClassicEditorKeyboardShortcut[] | undefined;
    readonly services?: readonly ClassicEditorImportExportService[] | undefined;
    readonly onCreate?: ((context: ClassicEditorHookContext) => void) | undefined;
    readonly onMount?: ((context: ClassicEditorHookContext) => void) | undefined;
    readonly onUpdate?: ((context: ClassicEditorHookContext) => void) | undefined;
    readonly onPaste?: ((context: ClassicEditorHookContext, event: QuireEditorPasteEvent) => boolean | void) | undefined;
    readonly onUnmount?: ((context: ClassicEditorHookContext) => void) | undefined;
    readonly onDestroy?: ((context: ClassicEditorHookContext) => void) | undefined;
}
```

**id** — 实例内唯一的稳定插件身份。

**audience** — 由插件声明继承的界面受众。

**contributions** — 声明式产品界面贡献。

**extensions** — 插件装入 Core 的扩展，位于预设与实例扩展之后。

**toolbarItems** — 独立声明的紧凑工具栏条目。

**contextMenuItems** — 独立声明的右键菜单。

**selectionPopupItems** — 独立声明的文字选区浮动条。

**contextualPopupItems** — 按目标身份组织的上下文弹出菜单。

**sidebarPanels** — 独立声明的侧栏面板。

**globalSettingsSections** — 全局设置中的独立章节。

**keyboardShortcuts** — 产品快捷键。

**services** — 具名导入导出服务。

**onCreate** — 产品实例与注册表创建后调用。

**onMount** — Core、View 和产品界面挂载后调用。

**onUpdate** — 产品配置或编辑器状态更新界面后调用。

**onPaste** — 在 Core 默认粘贴前同步决定是否接管事件，返回 true 后可启动异步宿主工作。
@param context - 当前产品上下文。
@param event - Core 粘贴事件与解析后的切片。
@returns 是否由该插件接管。

**onUnmount** — 可复用卸载释放 Core、View 和界面之前调用。

**onDestroy** — 最终销毁期间调用一次。

插件的 ID 在实例内唯一。`extensions` 放文档能力；`contributions`、toolbar、selection popup 与 sidebar 分别声明产品 surface；services 注册格式；生命周期区分可复用挂载与最终销毁。

## typed action

### ClassicEditorActionDefinition

`@quirekit/classic-editor` · AGPL-3.0-only

同一个直接绑定的动作定义可投影到多个产品界面。身份用于诊断，不充当字符串命令路由。

```ts
export interface ClassicEditorActionDefinition {
    readonly id: string;
    readonly label: ClassicEditorText;
    readonly icon?: string | undefined;
    readonly group?: string | undefined;
    readonly order: number;
    readonly shortcut?: ClassicEditorText | undefined;
    readonly isAvailable?: ((context: ClassicEditorActionContext) => boolean) | undefined;
    readonly canExecute?: ((context: ClassicEditorActionContext) => boolean) | undefined;
    readonly isActive?: ((context: ClassicEditorActionContext) => boolean) | undefined;
    readonly disabledReason?: ((context: ClassicEditorActionContext) => ClassicEditorActionReason | undefined) | undefined;
    readonly run: (context: ClassicEditorActionContext) => boolean | Promise<boolean>;
}
```

**id** — 用于诊断的稳定动作身份，不用于 DOM 字符串派发。

**label** — 投影控件使用的本地化默认标签。

**icon** — 可选的图标身份。

**group** — 用于目录呈现的语义分组。

**order** — 同组内的稳定顺序。

**shortcut** — 可见快捷键提示。

**isAvailable** — 产品是否安装了该动作所需能力。

**canExecute** — 当前状态下动作是否可执行。

**isActive** — 只读地检查切换状态。

**disabledReason** — 说明可见控件为何不可执行。

**run** — 经 Core 命令链、产品 UI 或宿主服务执行一次。

`run(context)` 的上下文包含 editor、instance、ui、root、locale、backend 和触发来源。`isAvailable`、`canExecute`、`isActive` 与 `disabledReason` 返回只读事实，不执行命令或外部请求。文档动作经 Core，UI 动作经 `context.ui`。

### createClassicEditorRibbonAction

`@quirekit/classic-editor` · AGPL-3.0-only

把一个直接绑定的 typed action 投影为功能区控件。
@param id - 稳定的贡献身份。
@param groupId - 所属功能区分组。
@param action - 共享动作定义。
@returns 功能区动作贡献。

```ts
function createClassicEditorRibbonAction(id: string, groupId: string, action: ClassicEditorActionDefinition): ClassicEditorActionRibbonControlContribution
```

返回的 groupId 必须与已声明分组一致；ID 不是另建命令路由的借口。真正可操作的插件见[产品插件教程](/build/product-plugin)。

## 可交互的面板

### ClassicEditorMountedRenderable

`@quirekit/classic-editor` · AGPL-3.0-only

交互贡献返回的框架中立挂载结果，明确元素、更新与销毁。

```ts
export interface ClassicEditorMountedRenderable {
    readonly element: Node | string | null;
    update?(context: ClassicEditorRenderContext): void;
    destroy(): void;
}
```

**element** — 追加到贡献宿主的 DOM 节点或文字。

**update** — 用最新上下文更新既有内容。
@param context - 当前已挂载的产品上下文。

**destroy** — 释放框架根、监听器和其他挂载资源。

render 只为一次挂载创建资源，update 刷新保留的 DOM/Vue 根，destroy 清理。要在面板里读最新 locale/selection，更新上下文引用；不要在 mount 时闭包一份永远不变的旧 context。

## 文件服务

### ClassicEditorImportExportService

`@quirekit/classic-editor` · AGPL-3.0-only

产品注册表中的格式服务；将文件副作用与规范文档修改分开。

```ts
export interface ClassicEditorImportExportService {
    readonly id: string;
    readonly label: ClassicEditorText;
    readonly format: ClassicEditorDocumentFormat;
    import?(context: ClassicEditorImportContext, input: ClassicEditorImportArtifact): void | Promise<void>;
    export?(context: ClassicEditorServiceContext): ClassicEditorExportArtifact | Promise<ClassicEditorExportArtifact>;
}
```

**id** — 稳定服务身份。

**label** — 本地化服务名称。

**format** — 服务提供的格式身份、扩展名和 MIME。

**import** — 解析 input 后，在 context.commit 内执行一次同步正文命令。context 提供取消 signal 与目标复核；同步或异步准备完成后返回。

**export** — 导出当前规范文档。
@param context - 当前产品服务上下文。
@returns 同步或异步产生的下载产物。

`instance.importDocument(serviceId, artifact)` 选择已注册服务，传入字符串或字节及文件名/MIME；`exportDocument(serviceId)` 返回 data/fileName/mimeType，下载由宿主负责。文件菜单另声明 `document-service` contribution，不因服务存在就自动创建所有菜单。

服务接收 `ClassicEditorImportContext`，先解析与校验输入，再通过 `context.commit(() => context.editor.commands.replaceDocument(document, { errorOnInvalidContent: true }))` 执行一次同步写入。commit 检查最新任务、原 Core、正文版本、可编辑状态和 signal；不能传 async 回调，命令返回 false 也视为失败。旧服务直接写入正文的实现必须迁移；任意绕过 commit 的副作用不能由产品自动回滚。

宿主传入第三个参数 `{ signal }` 可取消准备；新导入、正文编辑、只读更新或卸载也会使准备失效。官方 DOCX 服务已使用此边界，图片在提交前暂存。export 捕获开始时的正文，转换诊断通过 `onReport` 提供；产物只有 data/fileName/mimeType。完整调用与取消语义见[保存与文件](/classic/files)。
